2.3 如何得到真实的执行计划 除了10046事件: explain plan命令 DBMS_XPLAN包 SQLPLUS中的AUTOTRACE开关 这几种方法得到的执行计划都有可能是不准确的。 Oracle中判断得到的执行计划是否准确,就是看目标SQL是否被真正执行,真正执行过的SQL所对应的的执行计划就是准的,反之则有可能不准。注意,这里的判断原则从严格意义上来说并不适用于AUTOTRACE开关,因为所有使用AUTOTRACE开关所显示的执行计划都有可能是不准的,即使对应的目标SQL实际上已经执行过。 (1)、explain plan命令 因为此时SQL并没有被实际执行,可能不准的,尤其SQL包含绑定变量时。默认开启绑定变量窥探的情况下,对含绑定变量的目标SQL使用explain plan得到的执行计划只是一个半成品,Oracle随后对该SQL的绑定变量进行窥探后就得到了这些绑定变量具体的值,此时Oracle很可能会对上述半成品的执行计划做调整,一旦做了调整,使用explain plan命令得到的执行计划就不准了。 (2)、DBMS_XPLAN包 select * from table(dbms_xplan.display);执行计划可能不准,因为它只适用于查看使用explain plan命令得到的目标SQL的执行计划,目标SQL此时还没有被真正执行。 (3)、AUTOTRACE开关 SET AUTOTRACE ON和SET AUTOTRACE TRACEONLY,目标SQL都已被实际执行,所以SET AUTOTRACE ON和SET AUTOTRACE TRACEONLY能看到SQL的实际资源消耗情况。当使用SET AUTOTRACE TRACEONLY EXPLAIN时,如果执行的是SELECT语句,则并没有被实际执行,如果执行的是DML语句,会被Oracle实际执行。 使用SET AUTOTRACE ON、SET AUTOTRACE TRACEONLY和SET AUTOTRACE TRACEONLY EXPLAIN来获得DML语句的执行计划时要小心,因为这些DML语句实际已经被执行过了。 但即使执行过了,但所有使用SET AUTOTRACE命令所得到的的执行计划都有可能是不准的,因为使用SET AUTOTRACE命令所显示的执行计划都是来源于调用explain plan命令。
执行计划还在共享池中: 脚本:display_cursor_9i.sql 存储过程:printsql 得到真实的执行计划和资源消耗情况。 如果执行计划已经被age out出shared pool了,可以执行DBMS_XPLAN.DISPLAY_AWR或者使用AWR SQL报告(awrsqrpt.sql)和Statspack SQL报告来得到其历史执行计划和资源消耗。(sprepsql)
display_cursor_9i.sql适用于Oracle 9i及以后,执行脚本时传入待查勘执行计划的目标SQL的SQL HASH VALUE和CHILD CURSOR NUMBER。 9i中没有DBMS_XPLAN包中的DISPLAY_CURSOR方法,无法使用select * from table(dbms_xplan.display_cursor('sql_id/hash_value', child_cursor_number, 'advanced'));,但执行这个脚本可以得到真实执行计划。
如果执行计划已经被Oracle age out出shared pool,能否得到执行计划取决于:
1、10g以上版本,SQL执行的计划被Oracle捕获并存储到了AWR Repository中,则可以用AWR SQL得到真实执行。 2、9i,除非额外部署Statspack报告,并且采集Statspack报告的level值大于或等于6。
和DBMS_XPLAN.DISPLAY_AWR一样,AWR SQL报告显示的执行计划中也看不执行步骤对应的谓词条件,因为Oracle将执行计划的采样数据从V$SQL_PLAN挪到AWR Repository的基表WRH$_SQL_PLAN中时,没有保留V$SQL_PLAN中记录谓词条件的列ACCESS_PREDICATES和FILTER_PREDICATES的值。
SQL> desc WRH$_SQL_PLAN
Name Null Type
----------------------------------------- -------- ----------------------------
SNAP_ID NUMBER
DBID NOT NULL NUMBER
SQL_ID NOT NULL VARCHAR2(13)
PLAN_HASH_VALUE NOT NULL NUMBER
ID NOT NULL NUMBER
OPERATION VARCHAR2(30)
OPTIONS VARCHAR2(30)
OBJECT_NODE VARCHAR2(128)
OBJECT# NUMBER
OBJECT_OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(31)
OBJECT_ALIAS VARCHAR2(65)
OBJECT_TYPE VARCHAR2(20)
OPTIMIZER VARCHAR2(20)
PARENT_ID NUMBER
POSITION NUMBER
SEARCH_COLUMNS NUMBER
COST NUMBER
CARDINALITY NUMBER
BYTES NUMBER
OTHER_TAG VARCHAR2(35)
PARTITION_START VARCHAR2(5)
PARTITION_STOP VARCHAR2(5)
PARTITION_ID NUMBER
OTHER VARCHAR2(4000)
DISTRIBUTION VARCHAR2(20)
CPU_COST NUMBER
IO_COST NUMBER
TEMP_SPACE NUMBER
ACCESS_PREDICATES VARCHAR2(4000)
FILTER_PREDICATES VARCHAR2(4000)
PROJECTION VARCHAR2(4000)
TIME NUMBER
QBLOCK_NAME VARCHAR2(31)
REMARKS VARCHAR2(4000)
TIMESTAMP DATE
OTHER_XML CLOB
2.4 如何查看执行计划的执行顺序 先从最开头一直连续往右看,直到看到最右边的并列的地方; 对于不并列的,靠右的先执行; 如果见到并列的,就从上往下看,对于并列的部分,靠上的先执行。 select * from tabl