执行计划及树形语句

善若止水 2014-06-04 05:49:42
大家好:
今天想烦恼大家帮我分析分析执行计划,这块我一直是似懂非懂的。
下面是两种写法,仅仅是一个子查询,差异却很大的。
SQL> explain plan for( SELECT compid,compname,pcompid from companyinfo c
2 where vpd_year =(select max(vpd_year) from companyinfo ) and stopflag = 0 AND ACCBOOKID = 0
3 start with c.COMPID ='0600'
4 connect by prior c.compid = c.pcompid );

已解释。

SQL> select * from TABLE(DBMS_XPLAN.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1273742929

------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 93 | 4836 | 252 (1)| 00:00:04 |
|* 1 | FILTER | | | | | |
|* 2 | CONNECT BY WITH FILTERING| | | | | |
|* 3 | TABLE ACCESS FULL | COMPANYINFO | 10 | 690 | 252 (1)| 00:00:04 |
|* 4 | HASH JOIN | | | | | |
| 5 | CONNECT BY PUMP | | | | | |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
| 6 | TABLE ACCESS FULL | COMPANYINFO | 93 | 4836 | 252 (1)| 00:00:04 |
| 7 | SORT AGGREGATE | | 1 | 4 | | |
| 8 | TABLE ACCESS FULL | COMPANYINFO | 66199 | 258K| 252 (1)| 00:00:04 |
------------------------------------------------------------------------------------------

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

1 - filter("VPD_YEAR"= (SELECT MAX("VPD_YEAR") FROM "COMPANYINFO"
"COMPANYINFO") AND "STOPFLAG"=0 AND "ACCBOOKID"=0)
2 - access("C"."PCOMPID"=PRIOR "C"."COMPID")

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
3 - filter("C"."COMPID"='0600')
4 - access("C"."PCOMPID"=PRIOR "C"."COMPID")

已选择24行。

SQL> explain plan for( SELECT compid,compname,pcompid FROM (
2 SELECT compid,compname,pcompid from companyinfo c
3 where vpd_year =(select max(vpd_year) from companyinfo ) and stopflag = 0 AND ACCBOOKID = 0 )
4 start with COMPID ='0600'
5 connect by prior compid = pcompid);

已解释。

SQL> select * from TABLE(DBMS_XPLAN.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1904047111

-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 416 | 505 (1)| 00:00:07 |
|* 1 | CONNECT BY WITH FILTERING| | | | | |
|* 2 | TABLE ACCESS FULL | COMPANYINFO | 1 | 69 | 253 (2)| 00:00:04 |
| 3 | SORT AGGREGATE | | 1 | 4 | | |
| 4 | TABLE ACCESS FULL | COMPANYINFO | 66199 | 258K| 252 (1)| 00:00:04 |
|* 5 | HASH JOIN | | | | | |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
| 6 | CONNECT BY PUMP | | | | | |
|* 7 | TABLE ACCESS FULL | COMPANYINFO | 8 | 416 | 253 (2)| 00:00:04 |
| 8 | SORT AGGREGATE | | 1 | 4 | | |
| 9 | TABLE ACCESS FULL | COMPANYINFO | 66199 | 258K| 252 (1)| 00:00:04 |
-----------------------------------------------------------------------------------------

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

1 - access("PCOMPID"=PRIOR "COMPID")
2 - filter("COMPID"='0600' AND "STOPFLAG"=0 AND "ACCBOOKID"=0 AND "VPD_YEAR"=

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
(SELECT /*+ */ MAX("VPD_YEAR") FROM "COMPANYINFO" "COMPANYINFO"))
5 - access("PCOMPID"=PRIOR "COMPID")
7 - filter("STOPFLAG"=0 AND "ACCBOOKID"=0 AND "VPD_YEAR"= (SELECT
MAX("VPD_YEAR") FROM "COMPANYINFO" "COMPANYINFO"))

已选择26行。


两种sql的差异:
第二种是先做了一个子查询,再做树形查询。

两种sql的查询结果:
第一种查询速度极其缓慢,并且数据量达到了几千万,而数据源表companyinfo仅仅是几万,这明显是不对的。里面有大量的重复数据,去重之后是342行。
第二种查询速度很快,数据量也是342行,是我想要的数据。

我的理解:
这是因为第二种写法是子查询,先进行筛选,再做树查询。这我是可以理解的。关键是第一种,我就郁闷了,究竟是怎么执行的呢?

我的疑问:
1 以上的执行我是在sqlplus中通过spool 命令导出的,大家有没有别的导出执行计划的方法
2 我看执行计划执行顺序的依据是缩进,原则是"同级缩进上面的先执行,越往里越先执行",我的原则对吗?
3 依据上面的原则,我得出的执行顺序是,第一种写法 564328710 第二种 4326987510 ,大家赞成吗?
4 我比较了两者的执行计划,发现第二种比第一种少了一个"FILTER",多了"TABLE ACCESS FULL" 和"SORT AGGREGATE",大家有知道原因的吗?
5 id里面的"*"代表的是什么意思?比如"* 1",大家知道吗?
6 "SORT AGGREGATE"我的理解是排序的意思,我的语句里面就没有order by ,怎么有了排序操作?
7 最后的Predicate Information,我的理解是谓词信息,我能从中看到些什么?我发现,这里面的id顺序是和id里面标"*"的一致,这是一种巧合还是就是这样的?


...全文
165 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
小灰狼W 2014-06-05
  • 打赏
  • 举报
回复
昨天没看清楚问题,解释一下 1. 这个不纠结了,不是主要问题,spool 、截图都行 2. 这个缩进主要是根据执行计划的级别/深度(depth)来的,你说的顺序是对的 3. 3(56)8 和 42 97 4. 在第二个执行计划里,使用 SELECT compid,compname,pcompid from companyinfo c where vpd_year =(select max(vpd_year) from companyinfo ) and stopflag = 0 AND ACCBOOKID = 0 来进行connect by连接,因此(select max(vpd_year) from companyinfo )出现了两次,SORT AGGREGATE对应的是max()聚合的过程 5. *代表有谓词条件,具体的信息查看下面的Predicate Information 6. 聚合操作。聚合本身也是一个排序 7. 参照第5
善若止水 2014-06-05
  • 打赏
  • 举报
回复
引用 3 楼 wildwave 的回复:
昨天没看清楚问题,解释一下 1. 这个不纠结了,不是主要问题,spool 、截图都行 2. 这个缩进主要是根据执行计划的级别/深度(depth)来的,你说的顺序是对的 3. 3(56)8 和 42 97 4. 在第二个执行计划里,使用 SELECT compid,compname,pcompid from companyinfo c where vpd_year =(select max(vpd_year) from companyinfo ) and stopflag = 0 AND ACCBOOKID = 0 来进行connect by连接,因此(select max(vpd_year) from companyinfo )出现了两次,SORT AGGREGATE对应的是max()聚合的过程 5. *代表有谓词条件,具体的信息查看下面的Predicate Information 6. 聚合操作。聚合本身也是一个排序 7. 参照第5
谢谢版主,解释的浅显易懂。现在就结贴,100分全给版主了。
善若止水 2014-06-04
  • 打赏
  • 举报
回复
引用 1 楼 wildwave 的回复:
第一个执行计划里 filter("VPD_YEAR"= (SELECT MAX("VPD_YEAR") FROM "COMPANYINFO" "COMPANYINFO") AND "STOPFLAG"=0 AND "ACCBOOKID"=0) 是在最后过滤的 第二个执行计划,在里层先过滤,再做connect连接,数据量大大减少
谢谢楼主,我的理解的执行j计划的顺序是对的吗?我是不是仅仅看谓词信息里的执行顺序就好了?
小灰狼W 2014-06-04
  • 打赏
  • 举报
回复
第一个执行计划里 filter("VPD_YEAR"= (SELECT MAX("VPD_YEAR") FROM "COMPANYINFO" "COMPANYINFO") AND "STOPFLAG"=0 AND "ACCBOOKID"=0) 是在最后过滤的 第二个执行计划,在里层先过滤,再做connect连接,数据量大大减少

17,377

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧