-- 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