查看ORACLE执⾏计划的⼏种常⽤⽅法
SQL的执⾏计划实际代表了⽬标SQL在Oracle数据库内部的具体执⾏步骤,作为调优,只有知道了优化器选择的执⾏计划是否为当前情形下最优的执⾏计划,才能够知道下⼀步往什么⽅向。
执⾏计划的定义:执⾏⽬标SQL的所有步骤的组合。
我们⾸先列出查看执⾏计划的⼀些常⽤⽅法:
1. explain plan命令
PL/SQL Developer中通过快捷键F5就可以查看⽬标SQL的执⾏计划了。但其实按下F5后,实际后台调⽤的就是explain plan命令,相当于封装了该命令。
explain plan使⽤⽅法:
(1) 执⾏explain plan for + SQL
(2) 执⾏select * from table(dbms_xplan.display);
实验表准备:
SQL> desc test1;
Name  Null          Type
----------------------------------------- -------- ----------------------------
T1ID    NOT NULL NUMBER(38)
T1V                      VARCHAR2(10)
SQL> desc test2;
Name  Null          Type
----------------------------------------- -------- ----------------------------
T2ID    NOT NULL NUMBER(38)
T2V                      VARCHAR2(10)
实验:
SQL> set linesize 100
SQL> explain plan for select t1id, t1v, t2id, t2v from test1, test2 where test1.t1id = test2.t2id;
Explained.
第⼀步使⽤explain plan对⽬标SQL进⾏了explain,第⼆步使⽤select * from table(dbms_xplan.display)语句展⽰出该SQL的执⾏计划。
这⾥test2作为驱动表,进⾏了全表扫描,test1作为被驱动表,由于其包含主键,所以⽤的是索引全扫描。左侧ID带*号的第四步操作,表⽰有谓词条件,这⾥可以看到既使⽤了主键索引(access),⼜使⽤了过滤条件(filter)。
2. DBMS_XPLAN包
(1) select * from table(dbms_xplan.display);--上⾯以说明。
(2) select * from table(dbms_xplan.display_cursor(null, null, 'advanced'));
(3) select * from table(dbms_xplan.display_cursor('sql_id/hash_value', child_cursor_number, 'advanced'));
(4) select * from table(dbms_xplan.display_awr('sql_id'));
(2) select * from table(dbms_xplan.display_cursor(null, null, 'advanced'));
主要⽤于SQLPLUS中查看刚执⾏过SQL的执⾏计划。⾸先第三个参数可以选择'advanced':sql优化的几种方式
接下来,第三个参数使⽤'all':
可以看出'advanced'记录的信息要⽐'all’多,主要就是多⼀个Outline Data。Outline Data主要是执⾏SQL时⽤于固定执⾏计划的内部HINT组合,可以将这部分内容摘出来加到⽬标SQL中以固定其执⾏计划。
(3) select * from table(dbms_xplan.display_cursor('sql_id/hash_value', child_cursor_number, 'advanced'));
其中第⼀个参数可以输⼊SQL的sql_id或hash value,⽅法就是如果执⾏的SQL仍在库缓存中,则可以使⽤V$SQL查询:
其中,使⽤@dbsnake⼤⽜的SQL可以知道SQL_ID和HASH_VALUE的⼀⼀对应关系:
隐藏问题1:
这⾥的截图可能有点问题,结果并不准确,问题就出在这个SQL中使⽤的算法中,在另⼀篇博⽂中会仔细说明这个问题。
使⽤:
SQL> select * from table(dbms_xplan.display_cursor('1p2fk2v00c865', 0, 'advanced'));
select * from table(dbms_xplan.display_cursor('3221627077', 0, 'advanced'));
就可以查出对应这条SQL的执⾏计划,内容同(2)中的'advanced',这就不展⽰了。
注意这还有第⼆个参数child_cursor_number,指的是⼦游标编号,如果未⽣成新的⼦游标,则此处写的是0。
(2)和(3)的结论相近,区别就是(2)只是针对最近⼀次执⾏SQL查看执⾏计划,(3)可以针对仍在库缓存中的任意⼀次SQL查看执⾏计划。
(4) select * from table(dbms_xplan.display_awr('sql_id'));
(1)是使⽤explain plan for +SQL作为前提,(2)和(3)的前提则是SQL的执⾏计划还在共享池中,具体讲是在库缓存中。如果已经被age out交换出共享池,则不能⽤这两种⽅法了。若该SQL的执⾏计划被采集到AWR库中,则可以⽤(4)来查询历史执⾏计划。
隐藏问题2:
实验这部分内容发现使⽤select * from table(dbms_xplan.display_awr('sql_id'));并没有结果,@黄玮⽼师说有可能是AWR收集的是top的SQL,有可能测试⽤的SQL不是most intensive SQL,但我是⽤alter system flush shared_pool后执⾏的⼿⼯采集快照,还是未被AWR抓到,⽐较奇怪的问题,这个也会在另⼀篇博⽂中仔细说明。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。