[Oracle]获取执行计划的各方法总结(三)

2015-07-24 07:27:11 · 作者: · 浏览: 8
| TABLE ACCESS BY INDEX ROWID | T2 | 2 | 1 | 2 |00:00:00.01 | 2 | ----------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - access(("T1"."N"=18 OR "T1"."N"=19)) 6 - access("T1"."ID"="T2"."T1_ID") Note ----- - dynamic sampling used for this statement (level=2) 已选择29行。 优点:1.可以清晰的从STARTS得出表被访问多少。
2.可以清晰的从E-ROWS和A-ROWS中得到预测的行数和真实的行数,从而可以准确判断Oracle评估是否准确。
3.虽然没有专门的输出运行时的相关统计信息,但是执行计划中的BUFFERS就是真实的逻辑读的多少

缺陷:1.必须要等到语句真正执行完毕后,才可以出结果。
2.无法控制记录输屏打出,不像autotrace有 traceonly 可以控制不将结果打屏输出。
3.看不出递归调用的次数,看不出物理读的多少(不过逻辑读才是重点)

方法4(知道sql_id后,直接带入的方式,简单,就步骤1)

步骤1: select * from table(dbms_xplan.display_cursor('&sq_id')); (该方法是从共享池里得到)

注:
1. 还有一个方法,select * from table(dbms_xplan.display_awr('&sq_id'));(这是awr性能视图里获取到的)
2. 如果有多执行计划,可以用类似方法查出
select * from table(dbms_xplan.display_cursor('cyzznbykb509s',0));
select * from table(dbms_xplan.display_cursor('cyzznbykb509s',1));
select * from table(dbms_xplan.display_cursor('1a914ws3ggfsn'));
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------
SQL_ID  1a914ws3ggfsn, child number 0
-------------------------------------
SELECT  * FROM t1, t2 WHERE t1.id = t2.t1_id AND t1.n in(18,19)

Plan hash value: 3532430033
-------------------------------------------------------------------------------------------
| Id  | Operation                      | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |       |       |     6 (100)|          |
|   1 |  NESTED LOOPS                  |          |       |       |            |          |
|   2 |   NESTED LOOPS                 |          |     2 |  8138 |     6   (0)| 00:00:01 |
|   3 |    INLIST ITERATOR             |          |       |       |            |          |
|   4 |     TABLE ACCESS BY INDEX ROWID| T1       |     2 |  4056 |     2   (0)| 00:00:01 |
|*  5 |      INDEX RANGE SCAN          | T1_N     |     1 |       |     1   (0)| 00:00:01 |
|*  6 |    INDEX RANGE SCAN            | T2_T1_ID |     1 |       |     1   (0)| 00:00:01 |
|   7 |   TABLE ACCESS BY INDEX ROWID  | T2       |     1 |  2041 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access(("T1"."N"=18 OR "T1"."N"=19))
   6 - access("T1"."ID"="T2"."T1_ID")

Note
-----
   - dynamic sampling used for this statement (level=2)
优点:1.知道sql_id立即可得到执行计划,和explain plan for 一样无需执行;
2.可以得到真实的执行计划。(停,等等,啥真实的,刚才这几个套路中,还有假的执行计划的吗?)

缺陷: 1.没有输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况);
2.无法判断是处理了多少行;
3.无法判断表被访问了多少次。

方法5(10046TRACE)

步骤1:alter session set events '10046 trace name context forever,level 12'; (开启跟踪)
步骤2:执行你的语句
步骤3:alter session set events '10046 trace name context off'; (关闭跟踪)
步骤4:找到跟踪后产生的文件
步骤5:tkprof trc文件 目标文件 sys=no sort=prsela,exeela,fchela (格式化命令)
set autotace off
alter session set statistics_level=typical;     
alter session set events '10046 trace name context  forever,level 12';

SELECT  *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n in(18,19);   
   
alter session set events '10046 trace name context off';   
select d.value
|| '/'
|| LOWER (RTRIM(i.INSTANCE, CHR(0)))
|| '_ora_'
|| p.spid
|| '.trc' trace_file_name
from (select p.spid
      from v$mystat m,v$session s, v$process p
      where  m.statistic#=1 a