在ORACLE数据库里通常可以使用如下的四种方法来得到目标SQL的执行计划:
1,EXPLAIN PLAN命令
2,DBMS_XPLAN包
3,SQLPLUS中的AUTOTRACE开关
4,10046事件
除了第四种方法外,其他的三种方法得到的执行计划都有可能不准确。在ORACLE数据库中判断得到的执行计划是否准确,就是看目标SQL是否被真正的执行,真正执行过的SQL所对应的执行计划就是准确的,反之,则有可能不准确。
对于使用第二种方法(DBMS_XPLAN)而言,针对不同的应用场景,你可以选择如下四种方式的一种。
a, select * from table(dbms_xplan.display)
例如:
SQL> explain plan for select * from hr.employees;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1445457117
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 7276 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMPLOYEES | 107 | 7276 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------
8 rows selected.
b,select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
c,select * from table(dbms_xplan.display_cursor('sql_id/hash_value',child_cursor_number,'advanced'));
d,select * from table(dbms_xplan.display_awr('sql_id'));
Note:执行select * from table(dbms_xplan.display)所得到的执行计划可能是不准确的,因为它只是用于查看使用explain plan命令得到的目标SQL的执行计划,目标SQL此时还没有真正执行,所以用它得到的执行计划可能不正确。使用剩下的三种方式得到的执行计划都是准确的,因为此时的目标SQL都已经被实际执行过了。
对第三种方法(即使用SQLPLUS中的AUTOTRACE)而言,可以有下面几种方法来开启:
set autotrace on;(目标SQL都已经被执行)
set autotrace traceonly;(目标SQL都已经被执行)
set autotrace traceonly explain; (对于查询目标SQL时,是没有被实际执行,但是如果目标SQL是DML语句时,这个时候DML是实际上已经被执行了)
由于SET AUTOTRACE命令后显示的执行计划实际上是来源于调用EXPLIAN PLAN命令,而用EXPLAIN PLAN命令得到的执行计划有可能不准确(特别是在使用了绑定变量的情况下),所以使用SET AUTOTRACE命令所显示的执行计划也有可能不准确。
看一个如下的例子来验证下使用explain plan和set autotrace命令后得到的执行计划并不是目标SQL真实执行计划:
SQL> show user
USER is "HR"
SQL> create table T1 as select * from dba_objects;
Table created.
SQL> insert into t1 select * from t1;
50319 rows created.
SQL> commit;
Commit complete.
SQL> insert into t1 select * from t1;
100638 rows created.
SQL> commit;
Commit complete.
SQL> select count(*) from t1;
COUNT(*)
----------
201276
在表T1的OBJECT_ID列上建立一个单键值的B树索引IDX_T1
SQL> create index idx_t1 on t1(object_id);
Index created.
对T1表收集一下统计信息:
SQL> exec dbms_stats.gather_table_stats(ownname=>'HR',tabname=>'T1',estimate_percent=>100,cascade=>true);
PL/SQL procedure successfully completed.
创建2个绑定变量X和Y,X=0,Y=100000
SQL> var x number;
SQL> var y number;
SQL> exec :x :=0
PL/SQL procedure successfully completed.
SQL> exec :y :=100000
PL/SQL procedure successfully completed.
查看如下语句的执行计划:
SQL> explain plan for select count(*) from t1 where object_id between :x and :y;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2351893609
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | FILTER | | | | | |
|* 3 | INDEX RANGE SCAN| IDX_T1 | 503 | 2515 | 3 (0)| 00:00:01 |
------------------------