如何查看执行计划
1.执行计划的执行顺序
首先,执行计划是由各类操作符组成的一颗树,也就是排序好的操作符的展现形式,从内到外依次执行
(看执行计划一般看MANAGER中执行计划文本的方式,这样看的更详尽一点,计划可以拷贝到文本编辑工具UE,NOTEPAD++中,这样缩进更为明显)
一般的执行计划格式为
OP1
OP2
OP3
OP4
OP5
OP6
OP7
OP8
缩进越多的越先执行,同样缩进的上面的先执行,下面的后执行,上下的优先级高于内外,对于上面这个简单的例子,大家可以自己写一个执行顺序
这里做一些空行,看写的执行顺序是否和后面列出的一致
这个例子的执行顺序为
OP3->OP4->OP2->OP7->OP8->OP6->OPT5->OP1
2操作符的含义
操作符 | 说明 |
AAGR2 | 简单聚集;如果没有分组( group by ), 则总的就一个组,直接计算聚集函数 |
SSCN | 直接使用二级索引进行扫描 |
ASCN | 数组当作表来扫描 |
SSEK2 | 二级索引数据定位 |
CSCN2 | 聚集索引扫描 |
UNION | UNION 计算 |
DSCN | 动态视图表扫描 |
UNION | ALL UNION ALL 运算 |
CSEK2 | 聚集索引数据定位 |
NTTS2 | 临时表,临时存放数据 |
HAGR2 | HASH 分组,并计算聚集函数 |
NSET2 | 结果集 (result set) 收集, 一般是查询计划的顶层节点 |
HASH LEFT SEMI JOIN2 HASH | 左半连接 |
PARALLEL | 控制水平分区子表的扫描 |
HASH FULL JOIN2 HASH | 全外连接 |
PRJT2 | 关系的 ― 投影 ‖(project) 运算, 用于选择表达式项的计算 |
HASH LEFT JOIN2 HASH | 左外连接 |
NEST LOOP FULL JOIN2 | 嵌套循环全外连接 |
HASH RIGHT JOIN2 HASH | 右外连接 |
NEST LOOP INNER JOIN2 | 嵌套循环内连接 |
HASH RIGHT SEMI JOIN2 HASH | 右半连接 |
NEST LOOP LEFT JOIN2 | 嵌套循环左外连接 |
HEAP TABLE | 临时结果表 |
NEST LOOP SEMI JOIN2 | 嵌套循环半连接 |
HEAP TABLE SCAN | 临时结果表扫描 |
INDEX JOIN SEMI JOIN2 | 索引半连接 |
INDEX JOIN LEFT JOIN2 | 索引左连接 |
NEST LOOP INDEX JOIN2 | 索引内连接 |
1.3举例说明
这里我们举一个现实的例子,我们拟定一个这样执行计划的SQL
CREATE TABLE TEST5(ID INT);
CREATE TABLE TEST6(ID INT);
CREATE TABLE TEST7(ID INT);
CREATE TABLE TEST8(ID INT);
insert into test5 values(3);
insert into test6 values(4);
insert into test7 select level %100 from dual connect by level < 10000;
insert into test8 select level %100 from dual connect by level < 10000;
SQL> explain select /*+no_use_cvt_var*/* from
(select test5.id from test5,test6 where test5.id = test6.id)
a,(select id from (select test7.id from test7,test8 where test7.id = test8.id) group by id) b where a.id = b.id;
这个例子的执行计划,我们暂时不关注PRJT和NSET操作符,只看SQL的执行顺序:
6->7->5->12->13->11->9->3
换为人能理解的意思就是,首先执行TEST5和TEST6的HASH连接,然后执行TEST7,TEST8的HASH连接并将连接结果进行HASH分组,再将两个结果再次进行HASH连接得到最终结果集。
这个例子的SQL写法比较简单意义也是非常明确的,读懂SQL需要干什么可以把操作符顺序写下来不会很困难。同样的,只看到这个执行计划,我们需要能想出来这个SQL原本是什么样子。读懂SQL本身是关键,执行计划更多的是起一个提示作用,侧面告诉大家SQL需要做什么事情
能正常读取执行计划描述的执行顺序后,我们关注下执行计划各个节点的详细信息,执行计划中所有操作符的后面都会有一个三元组,如:
#CSCN2: [1, 9999, 4]
[1, 9999, 4]就是我们提到的这个三元组,3个数字分别表示该操作符的估算代价,该操作符的输出行数,该操作符涉及数据的行长。
#CSCN2: [1, 9999, 4] 表示的意义为,这是一个全表扫描操作,涉及的行数为9999,每场数据长度为4,整体代价估算为1。
我们将三元组中的第二项称为估算行数(card),在复杂查询中,估算行数对于执行计划以及SQL性能的影响很大。