如何解析oracle执行计划

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解析oracle执行计划相关的知识,希望对你有一定的参考价值。

一、通过PL/SQL Dev工具
1、直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果。其中,Cost表示cpu的消耗,单位为n%,Cardinality表示执行的行数,等价Rows。
2、先执行 EXPLAIN PLAN FOR select * from tableA where paraA=1,再 select * from table(DBMS_XPLAN.DISPLAY)便可以看到oracle的执行计划了,看到的结果和1中的一样,所以使用工具的时候推荐使用1方法。
注意:PL/SQL Dev工具的Command window中不支持set autotrance on的命令。还有使用工具方法查看计划看到的信息不全,有些时候我们需要sqlplus的支持。

二、通过sqlplus
1.最简单的办法
Sql> set autotrace on
Sql> select * from dual;
  执行完语句后,会显示explain plan 与 统计信息。
  这个语句的优点就是它的缺点,这样在用该方法查看执行时间较长的sql语句时,需要等待该语句执行成功后,才返回执行计划,使优化的周期大大增长。如果不想执行语句而只是想得到执行计划可以采用:
Sql> set autotrace traceonly
这样,就只会列出执行计划,而不会真正的执行语句,大大减少了优化时间。虽然也列出了统计信息,但是因为没有执行语句,所以该统计信息没有用处,如果执行该语句时遇到错误,解决方法为:
(1)在要分析的用户下:
Sqlplus > @ ?
dbmsadminutlxplan.sql
(2) 用sys用户登陆
Sqlplus > @ ?sqlplusadminplustrce.sql
Sqlplus > grant plustrace to user_name;
- - user_name是上面所说的分析用户

 2.用explain plan命令
(1) sqlplus > explain plan for select * from testdb.myuser
(2) sqlplus > select * from table(dbms_xplan.display);
  上面这2种方法只能为在本会话中正在运行的语句产生执行计划,即我们需要已经知道了哪条语句运行的效率很差,我们是有目的只对这条SQL语句去优化。其实,在很多情况下,我们只会听一个客户抱怨说现在系统运行很慢,而我们不知道是哪个SQL引起的。此时有许多现成的语句可以找出耗费资源比较多的语句,如:
SELECT ADDRESS, substr(SQL_TEXT,1,20) Text, buffer_gets, executions,
buffer_gets/executions AVG FROM v$sqlarea
WHERE executions>0 AND buffer_gets > 100000 ORDER BY 5;
ADDRESS TEXT BUFFER_GETS EXECUTIONS AVG
-------- ---------------------------------------- ----------- ---------- ------------------------------------------------------------
66D83D64 select t.name, (sel 421531 60104 7.01336017
66D9E8AC select t.schema, t.n 1141739 2732 417.913250
66B82BCC select s.synonym_nam 441261 6 73543.5
  从而对找出的语句进行进一步优化。当然我们还可以为一个正在运行的会话中运行的所有SQL语句生成执行计划,这需要对该会话进行跟踪,产生trace文件,然后对该文件用tkprof程序格式化一下,这种得到执行计划的方式很有用,因为它包含其它额外信息,如SQL语句执行的每个阶段(如Parse、Execute、Fetch)分别耗费的各个资源情况(如CPU、DISK、elapsed等)。

3、启用SQL_TRACE跟踪所有后台进程活动:
全局参数设置: .OracleHome/admin/SID/pfile中指定: SQL_TRACE = true (10g)
当前session中设置:
SQL> alter session set SQL_TRACE=true;
SQL> select * from dual;
SQL> alter session set SQL_TRACE=false;
对其他用户进行跟踪设置:
SQL> select sid,serial#,username from v$session where username='XXX';
SID SERIAL# USERNAME
------ ---------- ------------------
127 31923 A
128 54521 B
开启跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,true);
关闭跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,false);
然后使用oracle自带的tkprof命令行工具格式化跟踪文件。

4、使用10046事件进行查询:
10046事件级别:
Lv1 - 启用标准的SQL_TRACE功能,等价于SQL_TRACE
Lv4 - Level 1 + 绑定值(bind values)
Lv8 - Level 1 + 等待事件跟踪
Lv12 - Level 1 + Level 4 + Level 8
全局设定:
OracleHome/admin/SID/pfile中指定: EVENT="10046 trace name context forever,level 12"
当前session设定:
开启:SQL> alter session set events '10046 trace name context forever, level 8';
关闭:SQL> alter session set events '10046 trace name context off';
对其他用户进行设置:
SQL> select sid,serial#,username from v$session where username='XXX';
SID SERIAL# USERNAME
------ ---------- ------------------
127 31923 A

SQL> exec dbms_system.set_ev(127,31923,10046,8,'A');

5、使用tkprof格式化跟踪文件: (根据下面SQL语句得到的文件都不存在该目录下,郁闷啊,懵懂啊...)

一般,一次跟踪可以分为以下几步:
1、界定需要跟踪的目标范围,并使用适当的命令启用所需跟踪。
2、经过一段时间后,停止跟踪。此时应该产生了一个跟踪结果文件。
3、找到跟踪文件,并对其进行格式化,然后阅读或分析。
--使用一下SQL找到当前session的跟踪文件:
SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc' trace_file_namefrom( select p.spid from v$mystat m,v$session s, v$process pwhere m.statistic# = 1 and s.sid = m.sid and p.addr = s.paddr) p,( select t.instance from v$thread t,v$parameter vwhere v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,( select value from v$parameter where name = 'user_dump_dest' ) d;-- 其它用户的 session SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc' trace_file_name from ( select p.spid from v$session s, v$process p where s.sid= '27' and s. SERIAL#= '30' and p.addr = s.paddr) p, ( select t.instance from v$thread t,v$parameter v where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i, ( select value from v$parameter where name = 'user_dump_dest' ) d;

--查找后使用tkprof命令,将TRACE文件格式为到D盘的explain_format.txt文件中
SQL> $tkprof d:/oracle/admin/FZLGFM/udump/fzlgfm_ora_3468.trc d:/explain_format.txt

文件内容大致如下(看不太懂....懵懂啊.....天啊....神啊.....过几时就懂了/////////////)
TKPROF: Release 9.2.0.1.0 - Production on 星期二 4月 20 13:59:20 2010
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Trace file: d:/oracle/admin/FZLGFM/udump/fzlgfm_ora_3468.trc
Sort options: default
********************************************************************************
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call********************************************************************************
alter session set events '10046 trace name context forever, level 8'

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 0 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1 0.00 0.00 0 0 0 0

Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer goal: CHOOSE
Parsing user id: SYS
参考技术A 1. 预估执行计划 - Explain Plan
Explain plan以SQL语句作为输入,得到这条SQL语句的执行计划,并将执行计划输出存储到计划表中。
首先,在你要执行的SQL语句前加explain plan for,此时将生成的执行计划存储到计划表中,语句如下:
explain plan for SQL语句
然后,在计划表中查询刚刚生成的执行计划,语句如下:
select * from table(dbms_xplan.display);
注意:Explain plan只生成执行计划,并不会真正执行SQL语句,因此产生的执行计划有可能不准,因为:
1)当前的环境可能和执行计划生成时的环境不同;
2)不会考虑绑定变量的数据类型;
3)不进行变量窥视。
2. 查询内存中缓存的执行计划 (dbms_xplan.display_cursor)
如果你想获取正在执行的或刚执行结束的SQL语句真实的执行计划(即获取library cache中的执行计划),可以到动态性能视图里查询。方法如下:
1)获取SQL语句的游标
游标分为父游标和子游标,父游标由sql_id(或联合address和hash_value)字段表示,子游标由child_number字段表示。
如果SQL语句正在运行,可以从v$session中获得它的游标信息,如:
select status, sql_id, sql_child_number from v$session where status='ACTIVE' and ....
如果知道SQL语句包含某些关键字,可以从v$sql视图中获得它的游标信息,如:
select sql_id, child_number, sql_text from v$sql where sql_text like '%关键字%‘
2)获取库缓存中的执行计划
为了获取缓存库中的执行计划,可以直接查询动态性能视图v$sql_plan和v$sql_plan_statistics_all等,但更方便的方法是以sql_id和子游标为参数,执行如下语句:
select * from table(dbms_xplan.display_cursor('sql_id',child_number));
3)获取前一次的执行计划:
set serveroutput off
select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
3. 查询历史执行计划(dbms_xplan.display_awr)
AWR会定时把动态性能视图中的执行计划保存到dba_hist_sql_plan视图中,如果你想要查看历史执行计划,可以采用如下方法查询:
select * from table(dbms_xplan.display_awr('sql_id');
4. 在用sqlplus做SQL开发是(Autotrace)
set autotrace是sqlplus工具的一个功能,只能在通过sqlplus连接的session中使用,它非常适合在开发时测试SQL语句的性能,有以下几种参数可供选择:
SET AUTOTRACE OFF ---------------- 不显示执行计划和统计信息,这是缺省模式
SET AUTOTRACE ON EXPLAIN ------ 只显示优化器执行计划
SET AUTOTRACE ON STATISTICS -- 只显示统计信息
SET AUTOTRACE ON ----------------- 执行计划和统计信息同时显示
SET AUTOTRACE TRACEONLY ------ 不真正执行,只显示预期的执行计划,同explain plan

5. 生成Trace文件查询详细的执行计划 (SQL_Trace, 10046)
SQL_TRACE作为初始化参数可以在实例级别启用,也可以只在会话级别启用,在实例级别启用SQL_TRACE会导致所有进程的活动被跟踪,包括后台进程及所有用户进程,这通常会导致比较严重的性能问题,所以在一般情况下,我们使用sql_trace跟踪当前进程,方法如下:
SQL>alter session set sql_trace=true;
...被跟踪的SQL语句...
SQL>alter session set sql_trace=false;
如果要跟踪其它进程,可以通过Oracle提供的系统包DBMS_SYSTEM. SET_SQL_TRACE_IN_SESSION来实现,例如:
SQL> exec dbms_system.set_sql_trace_in_session(sid,serial#,true) --开始跟踪
SQL> exec dbms_system.set_sql_trace_in_session(sid,serial#,false) --结束跟踪
生成trace文件后,再用tkprof 工具将sql trace 生成的跟踪文件转换成易读的格式,语法如下:
tkprof inputfile outputfile
10046事件是SQL_TRACE的一个升级版,它也是追踪会话,生成Trace文件,只是它里面的内容更详细
参考技术B 要执行任何SQL语句,Oracle 必须推导出一个“执行计划”。查询的执行计划是 Oracle 将如何实现数据的检索,以满足给定 SQL 语句的描述。它只不过是其中包含的步骤及它们之间关系的顺序树。
执行计划树的基本规则如下:
执行计划将包含一个根,没有父(操作)
父(操作)可以有一个或更多的子(操作),其ID将小于子(操作)ID
一子(操作)可只有一个父(操作),显示时右缩进;含许多子(操作)时,缩进相同
下面是一个执行计划示例。

SQL> explain plan for
2 select e.empno, e.ename, d.dname
3 from emp e, dept d
4 where e.deptno = d.deptno
5 and e.deptno = 10;

Explained.

SQL> SELECT * FROM table(dbms_xplan.display(null,null,'basic'));

PLAN_TABLE_OUTPUT
------------------------------------------------
Plan hash value: 568005898

------------------------------------------------
| Id | Operation | Name |
------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT |
| 3 | INDEX UNIQUE SCAN | PK_DEPT |
| 4 | TABLE ACCESS FULL | EMP |
------------------------------------------------

使用上述的规则,可以说:
操作0是树的根,它有一个子操作,即操作1
操作1有两个子操作,即操作2和4
操作2有一子操作,即操作3
下面是执行计划的图形表示。如果解读该树:为执行操作1,需执行操作2和4;操作2先完成;为执行2,需执行其子操作3;为执行操作4,需执行操作2。

Operation 0
(SELECT STATEMENT)
|
|
|
Operation 1
(NESTED LOOPS)
/\
/ \
/ \
/ \
/ \
/ \
/ \
/ \
Operation 2 Operation 4
(TABLE ACCESS (TABLE ACCESS FULL)
BY INDEX ROWID)
|
|
|
Operation 3
(INDEX UNIQUE SCAN)

操作3访问DEPT表,使用 INDEX UNIQUE SCAN,并传递ROWID给操作2
操作2从DEPT表返回所有行给操作1
操作1对操作2返回的每一行执行操作4
操作4执行全表扫描(TABLE ACCESS FULL),应用过滤器E. DEPTNO = 10,返回结果行给操作1
操作1返回最后结果给操作0本回答被提问者和网友采纳

Oracle如何查看执行计划

一、通过PL/SQL Dev工具
1、直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果。其中,Cost表示cpu的消耗,单位为n%,Cardinality表示执行的行数,等价Rows。
2、先执行 EXPLAIN PLAN FOR select * from tableA where paraA=1,再 select * from table(DBMS_XPLAN.DISPLAY)便可以看到oracle的执行计划了,看到的结果和1中的一样,所以使用工具的时候推荐使用1方法。
注意:PL/SQL Dev工具的Command window中不支持set autotrance on的命令。还有使用工具方法查看计划看到的信息不全,有些时候我们需要sqlplus的支持。

二、通过sqlplus
1.最简单的办法
Sql> set autotrace on
Sql> select * from dual;
执行完语句后,会显示explain plan 与 统计信息。
这个语句的优点就是它的缺点,这样在用该方法查看执行时间较长的sql语句时,需要等待该语句执行成功后,才返回执行计划,使优化的周期大大增长。如果不想执行语句而只是想得到执行计划可以采用:
Sql> set autotrace traceonly
这样,就只会列出执行计划,而不会真正的执行语句,大大减少了优化时间。虽然也列出了统计信息,但是因为没有执行语句,所以该统计信息没有用处,如果执行该语句时遇到错误,解决方法为:
(1)在要分析的用户下:
Sqlplus > @ ?
dbmsadminutlxplan.sql
(2) 用sys用户登陆
Sqlplus > @ ?sqlplusadminplustrce.sql
Sqlplus > grant plustrace to user_name;
- - user_name是上面所说的分析用户

2.用explain plan命令
(1) sqlplus > explain plan for select * from testdb.myuser
(2) sqlplus > select * from table(dbms_xplan.display);
上面这2种方法只能为在本会话中正在运行的语句产生执行计划,即我们需要已经知道了哪条语句运行的效率很差,我们是有目的只对这条SQL语句去优化。其实,在很多情况下,我们只会听一个客户抱怨说现在系统运行很慢,而我们不知道是哪个SQL引起的。此时有许多现成的语句可以找出耗费资源比较多的语句,如:
SELECT ADDRESS, substr(SQL_TEXT,1,20) Text, buffer_gets, executions,
buffer_gets/executions AVG FROM v$sqlarea
WHERE executions>0 AND buffer_gets > 100000 ORDER BY 5;
ADDRESS TEXT BUFFER_GETS EXECUTIONS AVG
-------- ---------------------------------------- ----------- ---------- ------------------------------------------------------------
66D83D64 select t.name, (sel 421531 60104 7.01336017
66D9E8AC select t.schema, t.n 1141739 2732 417.913250
66B82BCC select s.synonym_nam 441261 6 73543.5
从而对找出的语句进行进一步优化。当然我们还可以为一个正在运行的会话中运行的所有SQL语句生成执行计划,这需要对该会话进行跟踪,产生trace文件,然后对该文件用tkprof程序格式化一下,这种得到执行计划的方式很有用,因为它包含其它额外信息,如SQL语句执行的每个阶段(如Parse、Execute、Fetch)分别耗费的各个资源情况(如CPU、DISK、elapsed等)。

3、启用SQL_TRACE跟踪所有后台进程活动:
全局参数设置: .OracleHome/admin/SID/pfile中指定: SQL_TRACE = true (10g)
当前session中设置:
SQL> alter session set SQL_TRACE=true;
SQL> select * from dual;
SQL> alter session set SQL_TRACE=false;
对其他用户进行跟踪设置:
SQL> select sid,serial#,username from v$session where username='XXX';
SID SERIAL# USERNAME
------ ---------- ------------------
127 31923 A
128 54521 B
开启跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,true);
关闭跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,false);
然后使用oracle自带的tkprof命令行工具格式化跟踪文件。

4、使用10046事件进行查询:
10046事件级别:
Lv1 - 启用标准的SQL_TRACE功能,等价于SQL_TRACE
Lv4 - Level 1 + 绑定值(bind values)
Lv8 - Level 1 + 等待事件跟踪
Lv12 - Level 1 + Level 4 + Level 8
全局设定:
OracleHome/admin/SID/pfile中指定: EVENT="10046 trace name context forever,level 12"
当前session设定:
开启:SQL> alter session set events '10046 trace name context forever, level 8';
关闭:SQL> alter session set events '10046 trace name context off';
对其他用户进行设置:
SQL> select sid,serial#,username from v$session where username='XXX';
SID SERIAL# USERNAME
------ ---------- ------------------
127 31923 A

SQL> exec dbms_system.set_ev(127,31923,10046,8,'A');

5、使用tkprof格式化跟踪文件: (根据下面SQL语句得到的文件都不存在该目录下,郁闷啊,懵懂啊...)

一般,一次跟踪可以分为以下几步:
1、界定需要跟踪的目标范围,并使用适当的命令启用所需跟踪。
2、经过一段时间后,停止跟踪。此时应该产生了一个跟踪结果文件。
3、找到跟踪文件,并对其进行格式化,然后阅读或分析。

--使用一下SQL找到当前session的跟踪文件:
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 and s.sid = m.sid and p.addr = s.paddr) p,
( select t.instance from v$thread t,v$parameter v
where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,
( select value from v$parameter where name = 'user_dump_dest' ) d;
-- 其它用户的 session
SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc' trace_file_name
from
( select p.spid from v$session s, v$process p
where s.sid= '27' and s. SERIAL#= '30' and p.addr = s.paddr) p,
( select t.instance from v$thread t,v$parameter v
where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,
( select value from v$parameter where name = 'user_dump_dest' ) d;

--查找后使用tkprof命令,将TRACE文件格式为到D盘的explain_format.txt文件中
SQL> $tkprof d:/oracle/admin/FZLGFM/udump/fzlgfm_ora_3468.trc d:/explain_format.txt

文件内容大致如下(看不太懂....懵懂啊.....天啊....神啊.....过几时就懂了/////////////)
TKPROF: Release 9.2.0.1.0 - Production on 星期二 4月 20 13:59:20 2010
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Trace file: d:/oracle/admin/FZLGFM/udump/fzlgfm_ora_3468.trc
Sort options: default
********************************************************************************
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
********************************************************************************
alter session set events '10046 trace name context forever, level 8'

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 0 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1 0.00 0.00 0 0 0 0

Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer goal: CHOOSE
Parsing user id: SYS
参考技术A 1、直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果。其中,Cost表示cpu的消耗,单位为n%,Cardinality表示执行的行数,等价Rows。
2、先执行 EXPLAIN PLAN FOR select * from tableA where paraA=1,再 select * from table(DBMS_XPLAN.DISPLAY)便可以看到oracle的执行计划了,看到的结果和1中的一样,所以使用工具的时候推荐使用1方法。
注意:PL/SQL Dev工具的Command window中不支持set autotrance on的命令。还有使用工具方法查看计划看到的信息不全,有些时候我们需要sqlplus的支持。

二、通过sqlplus
1.最简单的办法
Sql> set autotrace on
Sql> select * from dual;
执行完语句后,会显示explain plan 与 统计信息。
这个语句的优点就是它的缺点,这样在用该方法查看执行时间较长的sql语句时,需要等待该语句执行成功后,才返回执行计划,使优化的周期大大增长。如果不想执行语句而只是想得到执行计划可以采用:
Sql> set autotrace traceonly
参考技术B plsql developer的话,在sql命令窗口中,按F5就能看到执行计划
sqlplus的话:
方法一
第一步:登入sql/plus 执行命令(无先后顺序)
set time on; (说明:打开时间显示)
set autotrace on; (说明:打开自动分析统计,并显示SQL语句的运行结果)
set autotrace traceonly; (说明:打开自动分析统计,不显示SQL语句的运行结果)
二者选一个执行
第二步: 输入你要查看的sql 执行
第三步:查看结果 如图 (图怎么沾不上啊)
方法二
先执行 EXPLAIN PLAN FOR select * from G_GAMBLING gamb where gamb.active=1
再 select * from table(DBMS_XPLAN.DISPLAY)便可以看到oracle的执行计划了
参考技术C 1、直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果。其中,Cost表示cpu的消耗,单位为n%,Cardinality表示执行的行数,等价Rows。
2、先执行 EXPLAIN PLAN FOR select * from tableA where paraA=1,再 select * from table(DBMS_XPLAN.DISPLAY)便可以看到oracle的执行计划了,看到的结果和1中的一样,所以使用工具的时候推荐使用1方法。
参考技术D

1、登录PLSQL Developer工具:

2、在sql Windows窗口输入sql语句,按F5就可以看见执行计划了。

以上是关于如何解析oracle执行计划的主要内容,如果未能解决你的问题,请参考以下文章

Oracle如何查看执行计划

Oracle删除一条SQL在Shared Pool里缓存的执行计划的三种方法

Oracle性能优化之执行计划管理_超越OCP精通Oracle视频教程培训31

oracle sql的执行计划如何查看

Oracle执行计划

两个左连接SQL执行计划解析(Oracle和PGSQL对比):