Oracle子查询性能

廷珀姆

所以我有这个巨大的表SS(someID,someDate,...)。我需要将此表的一个子集连接到另一个表。子集由以下方式确定:从*中的someID输入SS中选择*(从中的date1和date2之间选择SS中的someID)。

在Oracle XA数据服务器上并行运行此命令时,尽管Oracle可以在SS表上实现99%的单元卸载效率,但是执行会花费较长的时间和TEMP空间,但是子集查询仍然将大量数据带回数据库中。数据库服务器正在与其他表联接。

无论如何,有什么可以提高效率的吗?例如Oracle不必发送回那么多的数据并利用更多的单元卸载效率?

下面是查询计划

PLAN_TABLE_OUTPUT
Plan hash value: 3198983388

---------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name           | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                |  1044K|   589M| 46101   (1)| 00:01:33 |        |      |            |
|   1 |  PX COORDINATOR                         |                |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)                   | :TQ10003       |  1044K|   589M| 46101   (1)| 00:01:33 |  Q1,03 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN BUFFERED                   |                |  1044K|   589M| 46101   (1)| 00:01:33 |  Q1,03 | PCWP |            |
|   4 |     PX RECEIVE                          |                |       |       |            |          |  Q1,03 | PCWP |            |
|   5 |      PX SEND HASH                       | :TQ10001       |       |       |            |          |  Q1,01 | P->P | HASH       |
|   6 |       NESTED LOOPS                      |                |       |       |            |          |  Q1,01 | PCWP |            |
|   7 |        NESTED LOOPS                     |                |   523K|   135M| 38264   (1)| 00:01:17 |  Q1,01 | PCWP |            |
|   8 |         SORT UNIQUE                     |                | 29402 |   401K| 13751   (1)| 00:00:28 |  Q1,01 | PCWP |            |
|   9 |          PX RECEIVE                     |                | 29402 |   401K| 13751   (1)| 00:00:28 |  Q1,01 | PCWP |            |
|  10 |           PX SEND HASH                  | :TQ10000       | 29402 |   401K| 13751   (1)| 00:00:28 |  Q1,00 | P->P | HASH       |
|  11 |            PX BLOCK ITERATOR            |                | 29402 |   401K| 13751   (1)| 00:00:28 |  Q1,00 | PCWC |            |
|* 12 |             INDEX STORAGE FAST FULL SCAN| SUPERSET_IDX1  | 29402 |   401K| 13751   (1)| 00:00:28 |  Q1,00 | PCWP |            |
|* 13 |         INDEX RANGE SCAN                | XU_SUPERSET_01 |    18 |       |     1   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|  14 |        TABLE ACCESS BY INDEX ROWID      | SUPERSET       |    18 |  4644 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|  15 |     PX RECEIVE                          |                |  2886K|   880M|  7834   (2)| 00:00:16 |  Q1,03 | PCWP |            |
|  16 |      PX SEND HASH                       | :TQ10002       |  2886K|   880M|  7834   (2)| 00:00:16 |  Q1,02 | P->P | HASH       |
|  17 |       PX BLOCK ITERATOR                 |                |  2886K|   880M|  7834   (2)| 00:00:16 |  Q1,02 | PCWC |            |
|  18 |        TABLE ACCESS STORAGE FULL        | POL_DTL        |  2886K|   880M|  7834   (2)| 00:00:16 |  Q1,02 | PCWP |            |
---------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access(SS.POL_ID=PD.POL_ID)
  12 - storage(IMPT_DT<=TO_DATE(' 2014-11-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND IMPT_DT>=TO_DATE(' 2014-10-28 
              00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
       filter(IMPT_DT<=TO_DATE(' 2014-11-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND IMPT_DT>=TO_DATE(' 2014-10-28 
              00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
  13 - access(SS.POL_ID=POL_ID)

Note
-----
   - Degree of Parallelism is 4 because of session

在此处输入图片说明

乔恩·海勒

您可能没有太多可以改善此查询的方法。执行计划看起来不错:

  1. 好的对象索引似乎很适合查询,尽管没有完整的定义很难说清楚。
  2. 基数好估计的行和实际的行接近。这强烈暗示优化器做得很好,并且正在选择接近最佳的计划。如果它可以正确估计行数,它将对访问路径,连接方法,连接顺序等做出明智的决定。即使时间估计是接近的,这也是很少的。看起来有很好的表和系统统计信息。
  3. 细胞卸载storage谓词和主动报告Cell offloading暗示细胞卸载工作正常,至少一次。
  4. 并行性大对象已经被并行处理。我看不到任何明显的并行问题。

以下是一些需要改进的想法,但是不要期望得到大幅度的改进:

  1. 全表扫描强制进行全表扫描,而不是带有诸如提示的索引范围扫描--+ no_index(superset XU_SUPERSET_01)使用多块读取(用于全扫描)和单元卸载(用于全扫描的直接路径读取,而不用于使用缓冲区高速缓存的索引范围扫描),全表扫描读取所有数据的效率可能比索引范围扫描读取较少的数据。
  2. 覆盖索引如果无法进行全表扫描,请使用包含所有返回和查询的列的索引创建表的瘦版本。这样可以获得完全扫描的好处(多块IO,单元卸载),但小于整个表。
  3. 更大的DOP并行度(DOP)没有神奇的数字。但是以我的经验,DOP的最佳位置几乎总是大于4。这可能会提高性能,但会占用更多资源。
  4. 重写查询?重写查询可以使智能扫描能够处理存储单元中的联接。尝试改变

    select * from SS where someID in 
      (select someID from SS where someDate is between date1 and date2)
    

    select distinct ss1.*
    from ss ss1
    join ss ss2
        on ss1.someID = ss2.someID
         and ss2.someDate is between date1 and date2
    

    这个新版本做了额外的工作。联接返回的行多于必要的行,然后需要使它们区分。如果这意味着可以在存储单元中进行联接,那么额外的工作可能是值得的。我找不到确切的资料来说明可以分担什么样的处理,但是至少可以进行某些类型的联接。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章