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