-- Start
我们可以通过 EXPLAIN PLAN 语句生成执行计划,该语句把执行计划保存到一个叫做 PLAN_TABLE 的表中,我们可以通过查询这个表来查看执行计划。下面是一个简单例子。
-- 生成执行计划
EXPLAIN PLAN
SET STATEMENT_ID = 'test'
FOR
select * from employees where employee_id < 10;
-- 由于 PLAN_TABLE 表非常复杂,Oracle 提供下面的方式察看执行计划
SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE', 'test', 'ALL'));
-- 如果你想察看更多细节,你也可以直接查询表
select * from plan_table where statement_id = 'test'
如果你使用的是 sqlplus 工具,你还可以通过它提供了 autotrace 功能来查看执行计划,你只需要下面的两步,非常简单,下面是一个简单的例子。
-- 第一步: 打开 autotrace
SQL> set autotrace on
-- 第二步: 执行 SQL 语句
SQL> select * from test;
上面查看执行计划的方式有一个缺陷,它们必须由人触发,随着执行环境,时间,统计信息等的不同,执行计划有可能不同,有没有办法查看已经执行过 SQL 的执行计划呢?答案是肯定的,下面是一个简单的例子。
-- 第一步: 通过下面的语句找到 SQL_ID
select SQL_ID,SQL_TEXT from v$sql
where sql_text like '%KAFKA_MSG_QUEUE%';
-- 第二步: 通过下面的方式查看执行计划
select * from V$SQL_PLAN where SQL_ID='g7b1uz8n2mdvf'
order by CHILD_NUMBER, id;
-- 注意,上面的语句可以查询出该语句多次的执行计划,你可以加上时间来过滤
select * from V$SQL_PLAN where SQL_ID='g7b1uz8n2mdvf'
and "TIMESTAMP"=TIMESTAMP '2015-08-20 19:38:06.000'
order by CHILD_NUMBER, id
-- 上面语句的结果可读性差,试一试下面的语句吧
select '| Operation |Object Name | Rows | Bytes| Cost |'
as "Explain Plan in library cache:" from dual
union all
select rpad('| '||substr(lpad(' ',1*(depth-1))||operation||
decode(options, null,'',' '||options), 1, 35), 36, ' ')||'|'||
rpad(decode(id, 0, '----------------------------',
substr(decode(substr(object_name, 1, 7), 'SYS_LE_', null, object_name)
||' ',1, 30)), 31, ' ')||'|'|| lpad(decode(cardinality,null,' ',
decode(sign(cardinality-1000), -1, cardinality||' ',
decode(sign(cardinality-1000000), -1, trunc(cardinality/1000)||'K',
decode(sign(cardinality-1000000000), -1, trunc(cardinality/1000000)||'M',
trunc(cardinality/1000000000)||'G')))), 7, ' ') || '|' ||
lpad(decode(bytes,null,' ',
decode(sign(bytes-1024), -1, bytes||' ',
decode(sign(bytes-1048576), -1, trunc(bytes/1024)||'K',
decode(sign(bytes-1073741824), -1, trunc(bytes/1048576)||'M',
trunc(bytes/1073741824)||'G')))), 6, ' ') || '|' ||
lpad(decode(cost,null,' ', decode(sign(cost-10000000), -1, cost||' ',
decode(sign(cost-1000000000), -1, trunc(cost/1000000)||'M',
trunc(cost/1000000000)||'G'))), 8, ' ') || '|' as "Explain plan"
from v$sql_plan sp
where sp.SQL_ID='g7b1uz8n2mdvf'
and "TIMESTAMP"=TIMESTAMP '2015-08-20 19:38:06.000';
怎么样?看不懂执行计划?看看下面的文章吧?
Oracle 查询优化器 -- 改写查询语句
Oracle 查询优化器 -- 访问路径
Oracle 查询优化器 -- 表连接方法
如果你觉得执行计划有问题,那么很有可能是因为表或索引的统计信息没有更新,不知道怎么查看统计信息?看看 《Oracle 查看收集统计信息》 吧
-- 更多参见:Oracle SQL 优化精萃-- 声明:转载请注明出处
-- Last edited on 2015-08-28
-- Created by ShangBo on 2015-07-28
-- End