如何获得SQL的执行计划1
如何获得SQL的执行计划
Oracle中的执行计划显示在执行一条SQL语句时必须执行的详细步骤,通常以表格形式呈现,但其实是树形结构。查看Oracle中的执行计划一般有以下几种方法(包括但不限于)。
1. explain plan
explain plan
只显示一条SQL的执行计划,但不会真正去执行它。当使用此命令生成执行计划后,还需要调用dbms_xplan
包去查看相关内容。在TOAD或者PL/SQL Developer查看的执行计划,其实也就是explain plan的变体,因此,有可能是不准确的执行计划。
1
|
SH@linora> explain plan for
|
explain plan
其实是将Oracle所产生的执行计划步骤写入PLAN_TABLE$,此表是一个全局临时表,因此,各个session只能看到自己执行的SQL所产生的执行计划。
1
|
SYS@linora> set long 9999
|
2. dbms_xplan
dbms_xplan有好几种调用方法,以下仅列出常用的三种方法(后面两种适合数据库在10g及以上的版本):
- display--输出plan table内容
- display_cursor--用于显示内存中的SQL执行计划
- display_awr--输出AWR中的历史SQL执行计划
2.1 DISPLAY
语法:
1
|
DBMS_XPLAN.DISPLAY(
|
不加任何参数:
1
|
SCOTT@linora> EXPLAIN PLAN FOR
|
添加ADVANCED参数(显示所有信息):
1
|
SCOTT@linora> SELECT * FROM table(DBMS_XPLAN.DISPLAY('','','ADVANCED'));
|
DISPLAY仅仅针对预估的执行计划,而不是真实的执行计划,尤其当SQL语句包含绑定变量时。
2.2 DISPLAY_CURSOR
语法:
1
|
DBMS_XPLAN.DISPLAY_CURSOR(
|
DISPLAY_CURSOR是显示内存中的执行计划,只要目标SQL的执行计划所在的child cursor还在shared pool中,就可以使用display_cursor来查看:
1
|
SCOTT@linora> SELECT /*+ display_cursor_example */ * FROM emp e, dept d
|
查看此语句的执行计划:
1
|
SCOTT@linora> set pagesize 9999
|
如果display_cursor不添加前面两个参数,则表示查看刚刚执行过的SQL的执行计划。如:
1
|
SCOTT@linora> SELECT * FROM emp e, dept d WHERE e.deptno = d.deptno;
|
2.3 DISPLAY_AWR
语法:
1
|
DBMS_XPLAN.DISPLAY_AWR(
|
如果某一条语句的执行计划已经从shared pool清除了,那么此时想要查看此SQL的执行计划,就只能从display_awr中查看了,通过display_awr获取的SQL执行计划来自dba_hist_sql_plan,但display_awr不能查看执行步骤中对应的谓词条件!
1
|
SCOTT@linora> SELECT * FROM emp e, dept d WHERE e.deptno = d.deptno;
|
需要注意的是,如果某目标SQL的执行计划已经不在shared pool中了,SQL的执行计划已经被Oracle捕获并且存储到了AWR的Repository中,才可以使用display_awr,且版本是10g以上;如果是9i,则需要部署statspack,且采集的level必须大于6才可查看历史SQL的执行计划。
3. auto trace
语法:
1
|
SCOTT@linora> set autotrace -h
|
set autot on/off
在当前sessions完全打开/关闭autotrace,同时输出结果及执行计划和资源消耗
1
|
SCOTT@linora> set autot on
|
set autot trace
只输出目标SQL执行计划和资源消耗,对于SQL执行结果则只显示执行结果的数量
1
|
SCOTT@linora> set autot trace
|
set autot trace exp
只输出SQL执行计划,而不会显示目标SQL的执行结果和资源消耗
1
|
SCOTT@linora> set autot trace exp
|
set autot trace stat
只输出SQL执行结果资源消耗,而不显示执行计划
1
|
SCOTT@linora> set autot trace stat
|
4. 10046事件
请参照前文Oracle追踪SQL的方法 10046及tkprof的相关介绍。
5. 总结
在以上四种方法中,都可以看到SQL的执行计划,但除了10046外,其他方法获得的执行计划,都有可能是不准确的。因此,如果要获得SQL的真实执行计划,最好使用10046事件进行跟踪(SQL_TRACE也是10046的一个级别)。
explain plan
对于此方法而言,目标SQL根本就没有被执行过,因此,该执行计划极有可能是不准确的,特别是含有绑定变量的情况下,针对于bind peeking,Oracle可能会根据绑定变量窥视进行执行计划的调整。
dbms_xplan
除了dbms_xplan.display执行计划可能不准确外,dbms_xplan.display_awr,dbms_xplan.display_cursor都是准确的执行计划,因为后面两个都表示目标SQL被真正执行过。
set autotrace
autotrace设置为on或者traceonly时,目标SQL已经被实际执行过了,但当使用set autot trace exp时,如果执行的是select语句,则该SQL不会被Oracle执行,如果是DML修改,此时的SQL是会被实际执行的。虽然使用auto trace on/traceonly目标SQL都会被执行,但是用这种方法得到的执行计划还有可能是不准确的,因为使用auto trace命令所显示的执行计划都是源于explain plan的调用,跟TOAD和PL/SQL Developer一样。要获得真实的执行计划,尽量采用10046事件或者dbms_xplan.display_cursor!!!
Reference:
基于Oracle的SQL优化