我有这个复杂的SQL查询:
SELECT f1 (d1.prdecdde),
f2 (d1.prdecdde),
f3 (d1.prdecdde),
f4 (1, d1.prdecdde, d1.prdenpol),
d1.prdeisin,
f6 (d1.prdecdde, a.POLIRCTB),
NVL (a.poliagtb, a.poliagta),
d1.prdedtpr,
prdeticu
FROM ( SELECT prdecdde,
prdenpol,
prdeano,
SUM (NVL (prdeval, 0)) valantes,
NULL valdepois,
prdedtpr,
prdeticu,
prdeisin
FROM stat_pro_det
WHERE prdedprv = '20151101'
AND prdecdde IN (700,
100,
610,
600,
710,
900,
910)
AND prdeval > 0
GROUP BY prdecdde,
prdenpol,
prdeano,
prdedtpr,
prdeticu,
prdeisin
UNION ALL
SELECT prdecdde,
prdenpol,
prdeano,
NULL,
SUM (NVL (prdeval, 0)) valdepois,
prdedtpr,
prdeticu,
prdeisin
FROM stat_pro_det
WHERE prdedprv = '20160727'
AND prdecdde IN (700,
100,
610,
600,
710,
900,
910)
AND prdeval > 0
GROUP BY prdecdde,
prdenpol,
prdeano,
prdedtpr,
prdeticu,
prdeisin) d1,
sgss.dtpoli a
WHERE a.policdde = d1.prdecdde AND a.polinpol = d1.prdenpol
HAVING SUM (NVL (d1.valdepois, 0) - NVL (d1.valantes, 0)) <> 0
GROUP BY d1.prdecdde,
d1.prdenpol,
d1.prdeano,
a.polirctb,
a.poliagta,
a.poliagtb,
d1.prdedtpr,
d1.prdeticu,
d1.prdeisin;
dtpoli
表的主键是:
CREATE UNIQUE INDEX SGSS.PK_DTPOLI ON SGSS.DTPOLI
(POLICDDE, POLINPOL)
以下是解释计划:
Plan hash value: 1960385779
--------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 19403 | 1705K| | 113K (1)| 00:00:05 |
|* 1 | FILTER | | | | | | |
| 2 | HASH GROUP BY | | 19403 | 1705K| 38M| 113K (1)| 00:00:05 |
|* 3 | HASH JOIN | | 388K| 33M| 23M| 111K (1)| 00:00:05 |
| 4 | TABLE ACCESS FULL | DTPOLI | 618K| 16M| | 6561 (7)| 00:00:01 |
| 5 | VIEW | | 388K| 22M| | 103K (1)| 00:00:05 |
| 6 | UNION-ALL | | | | | | |
| 7 | HASH GROUP BY | | 194K| 9304K| 13M| 52044 (1)| 00:00:03 |
| 8 | INLIST ITERATOR | | | | | | |
|* 9 | TABLE ACCESS BY INDEX ROWID| STAT_PRO_DET | 194K| 9304K| | 50003 (1)| 00:00:02 |
|* 10 | INDEX RANGE SCAN | STAT_PRO_DET_03 | 198K| | | 790 (2)| 00:00:01 |
| 11 | HASH GROUP BY | | 193K| 9264K| 13M| 51818 (1)| 00:00:03 |
| 12 | INLIST ITERATOR | | | | | | |
|* 13 | TABLE ACCESS BY INDEX ROWID| STAT_PRO_DET | 193K| 9264K| | 49784 (1)| 00:00:02 |
|* 14 | INDEX RANGE SCAN | STAT_PRO_DET_03 | 197K| | | 783 (2)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SUM(NVL("D1"."VALDEPOIS",0)-NVL("D1"."VALANTES",0))<>0)
3 - access("POLICDDE"="D1"."PRDECDDE" AND "POLINPOL"="D1"."PRDENPOL")
9 - filter("PRDEVAL">0)
10 - access("PRDEDPRV"='20151101' AND ("PRDECDDE"=100 OR "PRDECDDE"=600 OR "PRDECDDE"=610 OR
"PRDECDDE"=700 OR "PRDECDDE"=710 OR "PRDECDDE"=900 OR "PRDECDDE"=910))
13 - filter("PRDEVAL">0)
14 - access("PRDEDPRV"='20160727' AND ("PRDECDDE"=100 OR "PRDECDDE"=600 OR "PRDECDDE"=610 OR
"PRDECDDE"=700 OR "PRDECDDE"=710 OR "PRDECDDE"=900 OR "PRDECDDE"=910))
两列都是数字数据类型。使用提示parallel(#)
我可以改善效果,但我的重点是dtpoli PK
。
我无法找到为什么此查询不使用此主键索引并在DTPOLI表上使用全表扫描。这是因为我有一个Group by
条款?我真的不明白。
有帮助吗?
我正在使用Oracle 11gR2。
答案 0 :(得分:6)
它没有使用索引,因为这样做 效率更低。如果您从表中检索一小部分数据,索引很有用,但是当您获得大量数据时,使用索引会更慢。
原因是在索引中找到匹配的行需要磁盘访问才能获取索引块。这为您提供了数据记录的ROWID,然后您需要另一个磁盘访问来获取该数据块。每个索引和数据块必须至少读取一次,并且可能多次读取。
这些块可能位于缓冲区缓存中,但您仍然会两次触及,并且由于您正在跳转到索引和表格的不同部分,因此您增加了已经老化的东西 - 这意味着即使你最终从同一个物理数据块中获得两行,你最终也可能需要从磁盘读取两次。
全表扫描将一次性检索该表的所有数据块,因此它不必读取其中的任何数据块两次,并且没有额外的开销也可以读取索引块。
如果您仅引用主键(或任何其他索引)中的列,则可能会使用完整索引扫描。但是您要检索非索引数据,例如poliagtb
,因此也必须检索数据块。
您的主键是强制参照完整性。它还可以用于快速检索特定数据,但仅在适当时使用。优化者可以很好地决定它何时适合并且不合适。