Oracle 查看执行计划

-- Start

EXPLAIN PLAN

我们可以通过 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'


autotrace

如果你使用的是 sqlplus 工具,你还可以通过它提供了 autotrace 功能来查看执行计划,你只需要下面的两步,非常简单,下面是一个简单的例子。

-- 第一步: 打开 autotrace
SQL> set autotrace on

-- 第二步: 执行 SQL 语句
SQL> select * from test;

V$SQL_PLAN

上面查看执行计划的方式有一个缺陷,它们必须由人触发,随着执行环境,时间,统计信息等的不同,执行计划有可能不同,有没有办法查看已经执行过 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


你可能感兴趣的:(oracle,sql,plsql)