带有Oracle隐形索引的奇怪执行计划

时间:2019-04-07 01:41:22

标签: sql oracle indexing sql-execution-plan

我的问题是我在使用INVISIBLE索引时看到的一个奇怪的执行计划。 数据库11g

创建了两个不可见索引,用于特定查询的性能测试。

当我运行没有任何提示和参数OPTIMIZER_USE_INVISIBLE_INDEXES = FALSE的查询时,该查询正在执行预期的全表扫描,并在148秒内返回行,并行度为21(下面的查询#1)

当我使用提示/ * + USE_INVISIBLE_INDEXES * /和参数OPTIMIZER_USE_INVISIBLE_INDEXES = TRUE运行该查询时,该查询正在执行INDEX FAST FULL SCAN并在122秒内返回行,并行度为26(下面的查询2)< / p>

当我通过使用命名提示/ * + INDEX * /和参数OPTIMIZER_USE_INVISIBLE_INDEXES = TRUE命名索引来运行该查询时,该查询正在执行INDEX FULL SCAN和INDEX RANGE SCAN并花费649秒的最大时间,度为13的并行性(下面的查询3)

无论运行查询的顺序如何,d.o.p的趋势以及计划和执行时间都将保持这种方式。

好奇是否有人可以解释为什么命名索引会导致最高的成本和返回时间?如果必须使用索引,则必须为其命名。代码升级后,不能选择使用提示/ * + USE_INVISIBLE_INDEXES * /。

索引:

CREATE INDEX INVOICELINE_IDX_PRF2
ON INVOICELINE (invoiceheaderid, chargetypeid, agreementid, unpaidamount)
INVISIBLE COMPUTE STATISTICS ;

CREATE INDEX INVOICEHEADER_IDX_PRF0
ON INVOICEHEADER (id, TRUNC(invoiceduedate))
INVISIBLE COMPUTE STATISTICS ;

带提示:不使用提示;全表扫描

输出时间:148秒

查询#1:

    WITH V1
    AS 
    (
        SELECT 
             T1.agreementid             AS  agrmnt_id
            ,T1.invoicelineamount       AS  invc_line_amt
            ,TRUNC(T2.invoiceduedate)   AS  invc_due_dt
            ,T1.unpaidamount            AS  unpaid_amt
            ,T3.groupname               AS  grp_nm
        FROM
             INVOICELINE        T1
            ,INVOICEHEADER      T2
            ,CHARGETYPE         T3
        WHERE 1=1
          AND T2.id = T1.invoiceheaderid
          AND T3.id = T1.chargetypeid
    )
    SELECT /*+ PARALLEL(AUTO) */
        agrmnt_id, invc_due_dt, SUM(unpaid_amt) AS sum_amount
    FROM
        V1
    WHERE 1=1
      AND UPPER(grp_nm)='INSTALMENT'
    GROUP BY
        agrmnt_id, invc_due_dt
    ;

执行计划:

----------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                  | Name             | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                           |                  |       |       |       |  6329 (100)|          |        |      |            |
|   1 |  PX COORDINATOR                            |                  |       |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)                      | :TQ10003         |  1381K|    55M|       |  6329   (6)| 00:00:01 |  Q1,03 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                           |                  |  1381K|    55M|    68M|  6329   (6)| 00:00:01 |  Q1,03 | PCWP |            |
|   4 |     PX RECEIVE                             |                  |  1381K|    55M|       |  6329   (6)| 00:00:01 |  Q1,03 | PCWP |            |
|   5 |      PX SEND HASH                          | :TQ10002         |  1381K|    55M|       |  6329   (6)| 00:00:01 |  Q1,02 | P->P | HASH       |
|   6 |       HASH GROUP BY                        |                  |  1381K|    55M|    68M|  6329   (6)| 00:00:01 |  Q1,02 | PCWP |            |
|*  7 |        HASH JOIN                           |                  |  1381K|    55M|       |  5804   (6)| 00:00:01 |  Q1,02 | PCWP |            |
|   8 |         PX RECEIVE                         |                  |  1381K|    35M|       |  3928   (7)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |          PX SEND BROADCAST                 | :TQ10001         |  1381K|    35M|       |  3928   (7)| 00:00:01 |  Q1,01 | P->P | BROADCAST  |
|  10 |           VIEW                             | VW_GBC_13        |  1381K|    35M|       |  3928   (7)| 00:00:01 |  Q1,01 | PCWP |            |
|  11 |            HASH GROUP BY                   |                  |  1381K|    63M|    79M|  3928   (7)| 00:00:01 |  Q1,01 | PCWP |            |
|  12 |             PX RECEIVE                     |                  |  1381K|    63M|       |  3928   (7)| 00:00:01 |  Q1,01 | PCWP |            |
|  13 |              PX SEND HASH                  | :TQ10000         |  1381K|    63M|       |  3928   (7)| 00:00:01 |  Q1,00 | P->P | HASH       |
|  14 |               HASH GROUP BY                |                  |  1381K|    63M|    79M|  3928   (7)| 00:00:01 |  Q1,00 | PCWP |            |
|* 15 |                HASH JOIN                   |                  |  1381K|    63M|       |  3348   (8)| 00:00:01 |  Q1,00 | PCWP |            |
|  16 |                 JOIN FILTER CREATE         | :BF0000          |     6 |   162 |       |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|* 17 |                  TABLE ACCESS STORAGE FULL | CHARGETYPE       |     6 |   162 |       |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|  18 |                 JOIN FILTER USE            | :BF0000          |   138M|  2766M|       |  3324   (7)| 00:00:01 |  Q1,00 | PCWP |            |
|  19 |                  PX BLOCK ITERATOR         |                  |   138M|  2766M|       |  3324   (7)| 00:00:01 |  Q1,00 | PCWC |            |
|* 20 |                   TABLE ACCESS STORAGE FULL| INVOICELINE      |   138M|  2766M|       |  3324   (7)| 00:00:01 |  Q1,00 | PCWP |            |
|  21 |         PX BLOCK ITERATOR                  |                  |   129M|  1857M|       |  1855   (2)| 00:00:01 |  Q1,02 | PCWC |            |
|* 22 |          TABLE ACCESS STORAGE FULL         | INVOICEHEADER    |   129M|  1857M|       |  1855   (2)| 00:00:01 |  Q1,02 | PCWP |            |
----------------------------------------------------------------------------------------------------------------------------------------------------

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

    7 - access(T2.ID=ITEM_1)
    15 - access(T3.ID=T1.CHARGETYPEID)
    17 - storage(UPPER(T3.GROUPNAME)=U'INSTALMENT')
       filter(UPPER(T3.GROUPNAME)=U'INSTALMENT')
    20 - storage(:Z>=:Z AND :Z<=:Z AND SYS_OP_BLOOM_FILTER(:BF0000,T1.CHARGETYPEID))
       filter(SYS_OP_BLOOM_FILTER(:BF0000,T1.CHARGETYPEID))
    22 - storage(:Z>=:Z AND :Z<=:Z)

Note
-----
   - dynamic statistics used: dynamic sampling (level=AUTO)
   - automatic DOP: Computed Degree of Parallelism is 21

带有提示:/ * + USE_INVISIBLE_INDEXES * /

输出时间:122秒

查询2:

    WITH V1
    AS 
    (
        SELECT /*+ USE_INVISIBLE_INDEXES */
             T1.agreementid             AS  agrmnt_id
            ,T1.invoicelineamount       AS  invc_line_amt
            ,TRUNC(T2.invoiceduedate)   AS  invc_due_dt
            ,T1.unpaidamount            AS  unpaid_amt
            ,T3.groupname               AS  grp_nm
        FROM
             INVOICELINE        T1
            ,INVOICEHEADER      T2
            ,CHARGETYPE         T3
        WHERE 1=1
          AND T2.id = T1.invoiceheaderid
          AND T3.id = T1.chargetypeid
    )
    SELECT /*+ PARALLEL(AUTO) */
        agrmnt_id, invc_due_dt, SUM(unpaid_amt) AS sum_amount
    FROM
        V1
    WHERE 1=1
      AND UPPER(grp_nm)='INSTALMENT'
    GROUP BY
        agrmnt_id, invc_due_dt
    ;

执行计划:

---------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                    | Name                      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                             |                           |       |       |       |  1505 (100)|          |        |      |            |
|   1 |  PX COORDINATOR                              |                           |       |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)                        | :TQ10003                  |  1381K|    55M|       |  1505   (7)| 00:00:01 |  Q1,03 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                             |                           |  1381K|    55M|    68M|  1505   (7)| 00:00:01 |  Q1,03 | PCWP |            |
|   4 |     PX RECEIVE                               |                           |  1381K|    55M|       |  1505   (7)| 00:00:01 |  Q1,03 | PCWP |            |
|   5 |      PX SEND HASH                            | :TQ10002                  |  1381K|    55M|       |  1505   (7)| 00:00:01 |  Q1,02 | P->P | HASH       |
|   6 |       HASH GROUP BY                          |                           |  1381K|    55M|    68M|  1505   (7)| 00:00:01 |  Q1,02 | PCWP |            |
|*  7 |        HASH JOIN                             |                           |  1381K|    55M|       |  1082   (9)| 00:00:01 |  Q1,02 | PCWP |            |
|   8 |         PX RECEIVE                           |                           |  1381K|    35M|       |   815   (7)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |          PX SEND BROADCAST                   | :TQ10001                  |  1381K|    35M|       |   815   (7)| 00:00:01 |  Q1,01 | P->P | BROADCAST  |
|  10 |           VIEW                               | VW_GBC_13                 |  1381K|    35M|       |   815   (7)| 00:00:01 |  Q1,01 | PCWP |            |
|  11 |            HASH GROUP BY                     |                           |  1381K|    63M|    79M|   815   (7)| 00:00:01 |  Q1,01 | PCWP |            |
|  12 |             PX RECEIVE                       |                           |  1381K|    63M|       |   815   (7)| 00:00:01 |  Q1,01 | PCWP |            |
|  13 |              PX SEND HASH                    | :TQ10000                  |  1381K|    63M|       |   815   (7)| 00:00:01 |  Q1,00 | P->P | HASH       |
|  14 |               HASH GROUP BY                  |                           |  1381K|    63M|    79M|   815   (7)| 00:00:01 |  Q1,00 | PCWP |            |
|* 15 |                HASH JOIN                     |                           |  1381K|    63M|       |   346  (15)| 00:00:01 |  Q1,00 | PCWP |            |
|* 16 |                 TABLE ACCESS STORAGE FULL    | CHARGETYPE                |     6 |   162 |       |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|  17 |                 PX BLOCK ITERATOR            |                           |   138M|  2766M|       |   326  (10)| 00:00:01 |  Q1,00 | PCWC |            |
|* 18 |                  INDEX STORAGE FAST FULL SCAN| INVOICELINE_IDX_PRF2      |   138M|  2766M|       |   326  (10)| 00:00:01 |  Q1,00 | PCWP |            |
|  19 |         PX BLOCK ITERATOR                    |                           |   129M|  1857M|       |   250  (11)| 00:00:01 |  Q1,02 | PCWC |            |
|* 20 |          INDEX STORAGE FAST FULL SCAN        | INVOICEHEADER_IDX_PRF0    |   129M|  1857M|       |   250  (11)| 00:00:01 |  Q1,02 | PCWP |            |
---------------------------------------------------------------------------------------------------------------------------------------------------------------

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

    7 - access(T2.ID=ITEM_1)
    15 - access(T3.ID=T1.CHARGETYPEID)
    16 - storage(UPPER(T3.GROUPNAME)=U'INSTALMENT')
       filter(UPPER(T3.GROUPNAME)=U'INSTALMENT')
    18 - storage(:Z>=:Z AND :Z<=:Z)
    20 - storage(:Z>=:Z AND :Z<=:Z)

Note
-----
   - dynamic statistics used: dynamic sampling (level=AUTO)
   - automatic DOP: Computed Degree of Parallelism is 26

带有提示:/ * + INDEX(T1 INVOICELINE_IDX_PRF2)INDEX(T2 INVOICEHEADER_IDX_PRF0)* /

输出时间:649秒

查询3:

    WITH V1
    AS 
    (
        SELECT /*+ INDEX(T1 INVOICELINE_IDX_PRF2) INDEX(T2 INVOICEHEADER_IDX_PRF0) */
             T1.agreementid             AS  agrmnt_id
            ,T1.invoicelineamount       AS  invc_line_amt
            ,TRUNC(T2.invoiceduedate)   AS  invc_due_dt
            ,T1.unpaidamount            AS  unpaid_amt
            ,T3.groupname               AS  grp_nm
        FROM
             INVOICELINE        T1
            ,INVOICEHEADER      T2
            ,CHARGETYPE         T3
        WHERE 1=1
          AND T2.id = T1.invoiceheaderid
          AND T3.id = T1.chargetypeid
    )
    SELECT /*+ PARALLEL(AUTO) */
        agrmnt_id, invc_due_dt, SUM(unpaid_amt) AS sum_amount
    FROM
        V1
    WHERE 1=1
      AND UPPER(grp_nm)='INSTALMENT'
    GROUP BY
        agrmnt_id, invc_due_dt
    ;

执行计划:

----------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name                      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                           |       |       |       |   658K(100)|          |        |      |            |
|   1 |  PX COORDINATOR                         |                           |       |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)                   | :TQ10002                  |  1381K|    55M|       |   658K  (1)| 00:00:26 |  Q1,02 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                        |                           |  1381K|    55M|    68M|   658K  (1)| 00:00:26 |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE                          |                           |  1381K|    55M|       |   658K  (1)| 00:00:26 |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH                       | :TQ10001                  |  1381K|    55M|       |   658K  (1)| 00:00:26 |  Q1,01 | P->P | HASH       |
|   6 |       HASH GROUP BY                     |                           |  1381K|    55M|    68M|   658K  (1)| 00:00:26 |  Q1,01 | PCWP |            |
|   7 |        NESTED LOOPS                     |                           |  1381K|    55M|       |   657K  (1)| 00:00:26 |  Q1,01 | PCWP |            |
|   8 |         VIEW                            | VW_GBC_11                 |  1381K|    35M|       |   302K  (1)| 00:00:12 |  Q1,01 | PCWP |            |
|   9 |          HASH GROUP BY                  |                           |  1381K|    63M|    79M|   302K  (1)| 00:00:12 |  Q1,01 | PCWP |            |
|  10 |           PX RECEIVE                    |                           |  1381K|    63M|       |   302K  (1)| 00:00:12 |  Q1,01 | PCWP |            |
|  11 |            PX SEND HASH                 | :TQ10000                  |  1381K|    63M|       |   302K  (1)| 00:00:12 |  Q1,00 | P->P | HASH       |
|  12 |             HASH GROUP BY               |                           |  1381K|    63M|    79M|   302K  (1)| 00:00:12 |  Q1,00 | PCWP |            |
|  13 |              NESTED LOOPS               |                           |  1381K|    63M|       |   301K  (1)| 00:00:12 |  Q1,00 | PCWP |            |
|  14 |               PX BLOCK ITERATOR         |                           |       |       |       |            |          |  Q1,00 | PCWC |            |
|* 15 |                TABLE ACCESS STORAGE FULL| CHARGETYPE                |     6 |   162 |       |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|* 16 |               INDEX FULL SCAN           | INVOICELINE_IDX_PRF2      |   222K|  4569K|       | 50330   (1)| 00:00:02 |  Q1,00 | PCWP |            |
|* 17 |         INDEX RANGE SCAN                | INVOICEHEADER_IDX_PRF0    |     1 |    15 |       |     0   (0)|          |  Q1,01 | PCWP |            |
----------------------------------------------------------------------------------------------------------------------------------------------------------

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

    15 - storage(:Z>=:Z AND :Z<=:Z AND UPPER(T3.GROUPNAME)=U'INSTALMENT')
       filter(UPPER(T3.GROUPNAME)=U'INSTALMENT')
    16 - access(T3.ID=T1.CHARGETYPEID)
       filter(T3.ID=T1.CHARGETYPEID)
    17 - access(T2.ID=ITEM_1)

Note
-----
   - dynamic statistics used: dynamic sampling (level=AUTO)
   - automatic DOP: Computed Degree of Parallelism is 13

编辑

表计数

                                   SAMPLE_SIZE  LAST_ANALYZED
INVOICELINE    Count = 138,145,934  71258201    04-JUN-18
INVOICEHEADER  Count = 129,865,795 133224960    02-APR-19 
CHARGETYPE     Count = 620               597    15-JUN-18

1 个答案:

答案 0 :(得分:0)

嗯...我不能说我很惊讶。根据表格的行数,样本量和最后分析的信息,我想说,您最好的选择是至少对INVOICELINE和CHARGETYPE表格进行分析,如

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('owner', 'INVOICEHEADER');
  DBMS_STATS.GATHER_TABLE_STATS('owner', 'INVOICELINE');
  DBMS_STATS.GATHER_TABLE_STATS('owner', 'CHARGETYPE');
END;

将上方的“所有者”更改为表格的正确所有者。

CHARGETYPE是一个很小的表,可能不会对事物产生太大影响,但不会造成伤害。另一方面,自上次分析以来,INVOICELINE的规模几乎增加了一倍-而且该分析是在9个月前进行的,因此这些统计数据可能非常陈旧。试试看。

每当我看到计划中发生奇怪的事情时,我的第一个问题始终是“所涉及的表格的统计数据有多好?”。收集统计信息非常安全,除了可能需要花费一些时间才能运行这些过程外,不会产生任何负面影响,因此,通常是对此类问题的最佳攻击点。

好运。