【发布时间】:2016-04-10 15:21:54
【问题描述】:
我有一个问题 1:
select *
from (
select 'null' parentcode, u.unititemcode childcode, null unititempartnbr, null partoid,
null proccode, null unititemtype, null qualcat, null unititemgm2, null rsncode
from wi_unititem u where
u.prodproccode='PM11' and
u.prodendtime>sysdate-10
union all
select p.unititemcode parentcode, u.unititemcode childcode, 0 unititempartnbr, p.oid partoid,
p.proccode, u.unititemtype, u.qualcat, u.unititemgm2, u.rsncode
from wi_uitempart p, wi_unititem u where
p.unititemparttype='USEDSET' and
u.prodproccode=p.proccode and
u.setid=p.setid
) m
where m.unititemtype<>'SKID'
start with m.parentcode='null'
connect by prior m.childcode=m.parentcode
解释查询 1 的计划:
SELECT STATEMENT ALL_ROWSCost: 64 Bytes: 2 745 Cardinality: 9
23 FILTER
22 CONNECT BY WITH FILTERING
9 VIEW TIPSMSY. Cost: 12 Bytes: 610 Cardinality: 2
8 UNION-ALL
2 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 4 Bytes: 29 Cardinality: 1
1 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_PROCCODE_ENDTIME Cost: 3 Cardinality: 1
7 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 3 Bytes: 46 Cardinality: 1
6 NESTED LOOPS Cost: 8 Bytes: 113 Cardinality: 1
4 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UITEMPART Cost: 5 Bytes: 67 Cardinality: 1
3 INDEX RANGE SCAN INDEX (UNIQUE) TIPSMSY.WI_UITEMPART_PK Cost: 4 Cardinality: 1
5 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_SETID Cost: 2 Cardinality: 1
21 VIEW TIPSMSY. Cost: 64 Bytes: 2 745 Cardinality: 9
20 UNION-ALL
12 FILTER
11 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 4 Bytes: 29 Cardinality: 1
10 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_PROCCODE_ENDTIME Cost: 3 Cardinality: 1
19 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 3 Bytes: 46 Cardinality: 1
18 NESTED LOOPS Cost: 60 Bytes: 904 Cardinality: 8
16 NESTED LOOPS
13 CONNECT BY PUMP
15 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UITEMPART Cost: 18 Bytes: 938 Cardinality: 14
14 INDEX RANGE SCAN INDEX (UNIQUE) TIPSMSY.WI_UITEMPART_PK Cost: 4 Cardinality: 43
17 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_SETID Cost: 2 Cardinality: 1
查询2:
select *
from (
select 'null' parentcode, u.unititemcode childcode, null unititempartnbr, null partoid,
null proccode, null unititemtype, null qualcat, null unititemgm2, null rsncode
from wi_unititem u where
u.prodproccode='PM11' and
u.prodendtime>sysdate-20
union all
select p.unititemcode parentcode, u.unititemcode childcode, 0 unititempartnbr, p.oid partoid,
p.proccode, u.unititemtype, u.qualcat, u.unititemgm2, u.rsncode
from wi_uitempart p, wi_unititem u where
p.unititemparttype='USEDSET' and
u.prodproccode=p.proccode and
u.setid=p.setid
) m
where m.unititemtype<>'SKID'
start with m.parentcode='null'
connect by prior m.childcode=m.parentcode
解释查询 2 的计划:
SELECT STATEMENT ALL_ROWSCost: 122 Bytes: 82 655 Cardinality: 271
23 FILTER
22 CONNECT BY WITH FILTERING
9 VIEW TIPSMSY. Cost: 70 Bytes: 80 520 Cardinality: 264
8 UNION-ALL
2 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 62 Bytes: 7 627 Cardinality: 263
1 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_PROCCODE_ENDTIME Cost: 4 Cardinality: 263
7 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 3 Bytes: 46 Cardinality: 1
6 NESTED LOOPS Cost: 8 Bytes: 113 Cardinality: 1
4 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UITEMPART Cost: 5 Bytes: 67 Cardinality: 1
3 INDEX RANGE SCAN INDEX (UNIQUE) TIPSMSY.WI_UITEMPART_PK Cost: 4 Cardinality: 1
5 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_SETID Cost: 2 Cardinality: 1
21 VIEW TIPSMSY. Cost: 122 Bytes: 82 655 Cardinality: 271
20 UNION-ALL
12 FILTER
11 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 62 Bytes: 7 627 Cardinality: 263
10 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_PROCCODE_ENDTIME Cost: 4 Cardinality: 263
19 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UNITITEM Cost: 3 Bytes: 46 Cardinality: 1
18 NESTED LOOPS Cost: 60 Bytes: 904 Cardinality: 8
16 HASH JOIN
13 CONNECT BY PUMP
15 TABLE ACCESS BY INDEX ROWID TABLE TIPSMSY.WI_UITEMPART Cost: 18 Bytes: 938 Cardinality: 14
14 INDEX FULL SCAN INDEX (UNIQUE) TIPSMSY.WI_UITEMPART_PK Cost: 4 Cardinality: 43
17 INDEX RANGE SCAN INDEX TIPSMSY.WI_UNITITEM_SETID Cost: 2 Cardinality: 1
查询 1 包含“sysdate-10”,查询 2 包含“sysdate-20”,这是唯一的区别,查询 1 运行速度很快,而查询 2 运行速度很慢。
如果我们比较执行计划,那么可以在从 14 和 16 开始的行中发现差异: 查询 1 使用嵌套循环连接 + 索引范围扫描 查询2使用Hash Join + Index全扫描
查询2也可以使用查询1的执行计划吗?
【问题讨论】:
-
查询 2 正在处理更多数据。是什么让你认为查询 1 的计划是查询 2 增加数据的正确计划?
-
查询 2 返回的行数大约是查询 1 的 2 倍。查询 1 计划是正确的,因为发生索引全扫描的表 WI_UITEMPART 包含数百万个此类索引。查询 1 只产生大约 10000 行,这意味着查询 2 产生大约 20000 行。
-
两个查询的第一个选择有一个列
null unititemtype,然后是where m.unititemtype<>'SKID'。因为NULL永远不会等于或不等于NULL,所以第一个查询中的任何行都不会包含在最终结果中,除非以connect by 开头的内容带回了where子句消除的内容。另外,您是否尝试过将查询参数化为sysdate - :bind_variable?用 10 运行一次,然后 20,然后 20 应该重用计划。一个实验,而不是一个解决方案。 -
关于NULL:你是对的,但它不影响执行速度。正如你所说,我已经尝试使用绑定变量 - 计划与查询 2 相同(错误计划)
标签: oracle oracle10g nested-loops hierarchical