读懂执行计划有什么用呢?
执行计划贯穿Oracle调优始终。
了解执行计划的真实执行过程,将有助于优化。
对亍Oracle的原理理解有一定帮助。
读懂执行计划,SQL调优的第一步。
什么是SQL Execution Plan执行计划?
SQL是声明型语言,她只说我要去哪里,但很少告诉你到底如何去?
SQL语句的执行最终会落实为Oracle执行步骤的组合 =>【SQL执行计划】
查看执行计划的方法
SQLPLUS AUTOTRACE
Explain Plan For SQL
SQL_TRACE
使用DBMS_XPLAN包
V$SQL和V$SQL_PLAN
Enterprise Manager
其他第三方工具
如何使用sqlplus autotrace.
SQL> set autotrace help
Usage: SET AUTOT[RACE] {OFF | ON | TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]]
SQL> conn scott/tiger
Connected.
SQL> set autotrace on
SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled
SP2-0611: Error enabling STATISTICS report
普通用户要使用这个功能,必须建立plustrace角色,并且赋给该用户。Oracle已经为我们提供了这个脚本。
SQL> conn / as sysdba
Connected.
SQL> @?/sqlplus/admin/plustrce.sql
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR at line 1:
ORA-01919: role 'PLUSTRACE' does not exist
SQL> create role plustrace;
Role created.
SQL>
SQL> grant select on v_$sesstat to plustrace;
Grant succeeded.
SQL> grant select on v_$statname to plustrace;
Grant succeeded.
SQL> grant select on v_$mystat to plustrace;
Grant succeeded.
SQL> grant plustrace to dba with admin option;
Grant succeeded.
SQL>
SQL> set echo off
我们将plustrace角色赋予scott用户
SQL> grant plustrace to scott;
Grant succeeded.
再次执行set autotrace
SQL> conn scott/tiger
Connected.
SQL> set autotrace on
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- ---------------------------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Execution Plan
----------------------------------------------------------
Plan hash value: 3383998547
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 80 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DEPT | 4 | 80 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
65 recursive calls
0 db block gets
66 consistent gets
6 physical reads
0 redo size
802 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
4 rows processed
如上,结果分三部分
查询结果集、执行计划、统计信息。
set autotrace on 后面可以跟三个类型的参数:
traceonly -- 表示不执行真正的查询,只是把执行计划与统计信息打印出来。
explain -- 只打印查询结果和执行计划。
stat -- 只打印查询结果和统计信息。
执行计划解析:
Id 表示每一步的编号,并不表示执行的序列号。
Operation 表示执行步骤的名称
Name 表示对象的名称
Rows 表示查询结果返回的行数
Bytes 表示返回结果集的大小
Cost 表示执行计划的成本,用来衡量执行sql的速度,你可以把它想象成一个虚拟的时间单位。它的 计算方式比较复杂,依赖于系统的cpu、io等因素。
Time 语句执行的耗时
统计信息解析:
recursive calls :递归调用次数,为你执行的sql所执行的sql语句的条目
db block gets:用当前读方式从buffer cache中读取块数
consistent reads:用一致性读的方式从buffer cache中读取的块数。
physical reads:物理读,从磁盘上读取了多少个块。
redo size: sql产生的redo大小
bytes sent via SQL*Net to client:从服务器发往客户端的字节总数
bytes received via SQL*Net from client:客户机接受的字节数
SQL*Net roundtrips to/from client:从客户机到服务器之间发生SQL*Net的次数
sorts (memory):在内存中排序
sorts (disk):磁盘中排序
rows processed:影响数据的行数
下面我们看一个比较复杂的sql执行计划
SQL> set pagesize 200
SQL> set linesize 200
SQL> set autot on
SQL> select * from tab where rownum<=1;
TNAME TABTYPE CLUSTERID
------------------------------------------------------------------------------------------ --------------------- ----------
ACCESS$ TABLE
Execution Plan
----------------------------------------------------------
Plan hash value: 3245953645
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 106 | 4 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
|* 2 | FILTER | | | | | |
| 3 | NESTED LOOPS OUTER | | 1 | 106 | 4 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 99 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | I_OBJ5 | 1 | 77 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | I_USER2 | 1 | 22 | 1 (0)| 00:00:01 |
| 7 | TABLE ACCESS CLUSTER| TAB$ | 1 | 7 | 1 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | I_OBJ# | 1 | | 0 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 29 | 2 (0)| 00:00:01 |
|* 10 | INDEX SKIP SCAN | I_USER2 | 1 | 20 | 1 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | I_OBJ4 | 1 | 9 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=1)
2 - filter("O"."TYPE#"<>4 AND "O"."TYPE#"<>5 AND "O"."TYPE#"<>7 AND
"O"."TYPE#"<>8 AND "O"."TYPE#"<>9 AND "O"."TYPE#"<>10 AND "O"."TYPE#"<>11
AND "O"."TYPE#"<>12 AND "O"."TYPE#"<>13 AND "O"."TYPE#"<>14 AND
"O"."TYPE#"<>22 AND "O"."TYPE#"<>87 AND "O"."TYPE#"<>88 OR
BITAND("U"."SPARE1",16)=0 OR ("O"."TYPE#"=4 OR "O"."TYPE#"=5) AND
(SYS_CONTEXT('userenv','current_edition_name')='ORA$BASE' AND
"U"."TYPE#"<>2 OR "U"."TYPE#"=2 AND "U"."SPARE2"=TO_NUMBER(SYS_CONTEXT('use
renv','current_edition_id')) OR EXISTS (SELECT 0 FROM SYS."USER$"
"U2",SYS."OBJ$" "O2" WHERE "O2"."OWNER#"="U2"."USER#" AND "O2"."TYPE#"=88
AND "O2"."DATAOBJ#"=:B1 AND "U2"."TYPE#"=2 AND
"U2"."SPARE2"=TO_NUMBER(SYS_CONTEXT('userenv','current_edition_id')))))
5 - access("O"."SPARE3"=USERENV('SCHEMAID') AND "O"."TYPE#">=2 AND
"O"."LINKNAME" IS NULL AND "O"."TYPE#"<=5)
filter("O"."TYPE#"<=5 AND "O"."TYPE#">=2 AND "O"."LINKNAME" IS NULL)
6 - access("O"."OWNER#"="U"."USER#")
8 - access("O"."OBJ#"="T"."OBJ#"(+))
10 - access("U2"."TYPE#"=2 AND "U2"."SPARE2"=TO_NUMBER(SYS_CONTEXT('usere
nv','current_edition_id')))
filter("U2"."TYPE#"=2 AND "U2"."SPARE2"=TO_NUMBER(SYS_CONTEXT('usere
nv','current_edition_id')))
11 - access("O2"."DATAOBJ#"=:B1 AND "O2"."TYPE#"=88 AND
"O2"."OWNER#"="U2"."USER#")
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
153 consistent gets
0 physical reads
0 redo size
675 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
这个执行计划,不单复杂,而且多出了一块
Predicate Information (identified by operation id):
前面的序号,和执行计划中的id对应。filter表示表过滤条件,access表示索引过滤。
执行计划到底该怎么解读呢?
我们先把执行计划以‘树’的形式画出来。
从0开始,用缩进表示父子关系。
0的儿子为1
1的儿子为2
2的儿子为3和9
3的儿子为4和7
4的儿子为5,6
7的儿子为8
9的儿子为10,11
如下图:
正确的计划树形图解析顺序
树形图的解析过程:
1.从顶部开始。
2.在树中向左下移,直至到达左节点(没有子节点的节点)。首先执行此节点。
3.查看此行源的同级行源。接下来执行这些行源。
4.执行子行源后,接着执行父行源。
5.在树中不断上移,直至用完所有行源为止。
上图的执行顺序:
1.左下移动5节点没有子节点,优先执行5
2.遍历5的同级别行源6,执行6
3.执行4
4.遍历同级节点7,执行其子节点8
5.执行3
6.遍历同级节点,执行其最左下节点,执行10
7.执行11
8.执行9
9.执行2
10.执行1
11.执行0
二、Explain Plan For SQL
SQL> explain plan for select * from emp;
Explained.
显示执行计划
SQL> @?/rdbms/admin/utlxpls
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 532 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMP | 14 | 532 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
8 rows selected.
这种方法并没有真正的执行sql语句,查看执行计划也比较麻烦,基本上不使用。
三、SQL_TRACE
SQL_TRACE是Oracle的一个非常强大的工具。打开SQL_TRACE就可以逐步捕获任何一个会话的数据库活动,或者捕获整个数据库的活动,并将数据库活动记录成跟踪文件。每次使用完之后需要关闭跟踪,否则会降低系统的性能。
跟踪整个数据库实例。
只需要简单的修改参数文件(pfile/spfile)参数 SQL_TRACE = TRUE ,在全局启用SQL_TRACE会导致所有进程的活动被跟踪,包括后台进程及所有用户进程,这样也会数据库导致性能下降比较明显。
会话级跟踪。
SQL_TRACE的通常使用方式是仅跟踪一个会话。被跟踪的会话可以是您自己的,也可以是其它用户的会话。如果是自己的会话,只需要在SQL*PLUS中运行一下命令即可:
SQL> alter session set sql_trace = true;
类似的如果取消对会话的跟踪,运行一下命令:
SQL> alter session set sql_trace = false;
如果需要跟踪一个特定的会话,首先需要获取会话的SID和Serial#,这些信息可以在视图V$SESSION中获得,一旦知道了这两个参数,就可以运行一下命令:
SQL> execute SYS.dbms_system.set_sql_trace_in_session(13,9,true);
同样也可以使用这个过程关闭会话跟踪:
SQL> execute SYS.dbms_system.set_sql_trace_in_session(13,9,false);
跟踪文件的位置:
一旦为会话激活了SQL_TRACE,ORACLE就会在udump管理区创建跟踪文件,文件的目标位置由参数user_dump_dest来确定。每个操作都不会覆盖原来的文件,新的跟踪记录将会被追加到文件末尾。通常情况下,可以根据文件的修改时间判断目录下哪个文件是最新的文件。
SQL> show parameter user_dump_dest
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
user_dump_dest string /u01/app/oracle/diag/rdbms/11g
dg1/dgtst/trace
SQL>
也可以通过以下SQL来确定文件名:
SQL> 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;
TRACE_FILE_NAME
-----------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11347.trc
计时信息:
为了最大限度的利用跟踪文件,应该打开计时标志,通过参数TIMED_STATISTICTS=TRUE进行设置,这样可以对每个SQL语句的执行时间等进行记录,这个功能对系统性能的负担很小。
打开会话的计时信息:
SQL> alter session set timed_statistics = true ;
打开数据库系统的计时信息
SQL> alter system set timed_statistics = true ;
我们来做一个实验:
SQL> alter session set sql_trace=true;
ERROR:
ORA-01031: insufficient privileges
SQL> conn / as sysdba
Connected.
SQL> grant alter session to scott;
Grant succeeded.
执行一个查询
SQL> alter session set sql_trace=true;
Session altered.
SQL> select * from emp,dept where emp.deptno=dept.deptno;
获取trace_file_name
TRACE_FILE_NAME
----------------------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11450.trc
查看trace file
11gdg1-> cat /u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11450.trc
Trace file /u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11450.trc
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/11.2.0/db_1
System name: Linux
Node name: 11gdg1.localdomain.com
Release: 2.6.39-400.17.1.el6uek.x86_64
Version: #1 SMP Fri Feb 22 18:16:18 PST 2013
Machine: x86_64
VM name: VMWare Version: 6
Instance name: dgtst
Redo thread mounted by this instance: 1
Oracle process number: 23
Unix process pid: 11450, p_w_picpath: [email protected] (TNS V1-V3)
*** 2015-07-13 09:38:29.695
*** SESSION ID:(42.57) 2015-07-13 09:38:29.695
*** CLIENT ID:() 2015-07-13 09:38:29.695
*** SERVICE NAME:(SYS$USERS) 2015-07-13 09:38:29.695
*** MODULE NAME:(SQL*Plus) 2015-07-13 09:38:29.695
*** ACTION NAME:() 2015-07-13 09:38:29.695
=====================
PARSING IN CURSOR #139672104506696 len=32 dep=0 uid=83 oct=42 lid=83 tim=1436751509693664 hv=1569151342 ad='7f07f227fe10' sqlid='4tk6t8tfsfqbf'
alter session set sql_trace=true
END OF STMT
EXEC #139672104506696:c=0,e=601,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1436751509693625
*** 2015-07-13 09:38:47.624
CLOSE #139672104506696:c=0,e=17,dep=0,type=0,tim=1436751527624224
=====================
PARSING IN CURSOR #139672104506696 len=51 dep=0 uid=83 oct=3 lid=83 tim=1436751527625170 hv=4289413451 ad='8bd40480' sqlid='arvwqrbzuqhab'
select * from emp,dept where emp.deptno=dept.deptno
END OF STMT
PARSE #139672104506696:c=0,e=814,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=844388907,tim=1436751527625164
EXEC #139672104506696:c=0,e=315,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=844388907,tim=1436751527625549
FETCH #139672104506696:c=1000,e=1189,p=0,cr=8,cu=0,mis=0,r=1,dep=0,og=1,plh=844388907,tim=1436751527641018
FETCH #139672104506696:c=0,e=52,p=0,cr=2,cu=0,mis=0,r=13,dep=0,og=1,plh=844388907,tim=1436751527641868
STAT #139672104506696 id=1 cnt=14 pid=0 pos=1 obj=0 op='MERGE JOIN (cr=10 pr=0 pw=0 time=1393 us cost=6 size=812 card=14)'
STAT #139672104506696 id=2 cnt=4 pid=1 pos=1 obj=75333 op='TABLE ACCESS BY INDEX ROWID DEPT (cr=4 pr=0 pw=0 time=605 us cost=2 size=80 card=4)'
STAT #139672104506696 id=3 cnt=4 pid=2 pos=1 obj=75334 op='INDEX FULL SCAN PK_DEPT (cr=2 pr=0 pw=0 time=286 us cost=1 size=0 card=4)'
STAT #139672104506696 id=4 cnt=14 pid=1 pos=2 obj=0 op='SORT JOIN (cr=6 pr=0 pw=0 time=818 us cost=4 size=532 card=14)'
STAT #139672104506696 id=5 cnt=14 pid=4 pos=1 obj=75335 op='TABLE ACCESS FULL EMP (cr=6 pr=0 pw=0 time=766 us cost=3 size=532 card=14)'
如果你直接用cat命令查看上面的文件的话,根本看不懂。Oracle提供了一个工具TKPROF
11gdg1-> tkprof /u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11450.trc trace.sql TKPROF: Release 11.2.0.3.0 - Development on Mon Jul 13 09:41:05 2015 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
11gdg1-> cat trace.sql TKPROF: Release 11.2.0.3.0 - Development on Mon Jul 13 09:41:05 2015 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved. Trace file: /u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11450.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 ******************************************************************************** SQL ID: 4tk6t8tfsfqbf Plan Hash: 0 alter session set sql_trace=true 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 mode: ALL_ROWS Parsing user id: 83 ******************************************************************************** SQL ID: arvwqrbzuqhab Plan Hash: 844388907 select * from emp,dept where emp.deptno=dept.deptno call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 10 0 14 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 4 0.00 0.00 0 10 0 14 Misses in library cache during parse: 0 Optimizer mode: ALL_ROWS Parsing user id: 83 Number of plan statistics captured: 1 Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 14 14 14 MERGE JOIN (cr=10 pr=0 pw=0 time=1393 us cost=6 size=812 card=14) 4 4 4 TABLE ACCESS BY INDEX ROWID DEPT (cr=4 pr=0 pw=0 time=605 us cost=2 size=80 card=4) 4 4 4 INDEX FULL SCAN PK_DEPT (cr=2 pr=0 pw=0 time=286 us cost=1 size=0 card=4)(object id 75334) 14 14 14 SORT JOIN (cr=6 pr=0 pw=0 time=818 us cost=4 size=532 card=14) 14 14 14 TABLE ACCESS FULL EMP (cr=6 pr=0 pw=0 time=766 us cost=3 size=532 card=14) ******************************************************************************** OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 2 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 10 0 14 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 5 0.00 0.00 0 10 0 14 Misses in library cache during parse: 0 Misses in library cache during execute: 1 OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 0 0.00 0.00 0 0 0 0 Execute 0 0.00 0.00 0 0 0 0 Fetch 0 0.00 0.00 0 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 0 0.00 0.00 0 0 0 0 Misses in library cache during parse: 0 2 user SQL statements in session. 0 internal SQL statements in session. 2 SQL statements in session. ******************************************************************************** Trace file: /u01/app/oracle/diag/rdbms/11gdg1/dgtst/trace/dgtst_ora_11450.trc Trace file compatibility: 11.1.0.7 Sort options: default 1 session in tracefile. 2 user SQL statements in trace file. 0 internal SQL statements in trace file. 2 SQL statements in trace file. 2 unique SQL statements in trace file. 44 lines in trace file. 17 elapsed seconds in trace file.
四、使用DBMS_XPLAY
DBMS_XPLAN提供了5个函数
DISPLAY - 格式化和显示plan table中的内容。
DISPLAY_AWR - 格式化和显示存储在AWR中的sql语句的执行计划。
DISPLAY_CURSOR - 格式化和显示任意shared pool中加载的sql语句的执行计划。
DISPLAY_SQL_PLAN_BASELINE - 显示被SQL handle标识的SQL语句的一个或者多个执行计划。
DISPLAY_SQLSET - 格式化和显示存储在SQL tuning set中的sql语句的执行计划
1.DISPLAY
SQL> EXPLAIN PLAN FOR
SELECT * FROM emp e, dept d
WHERE e.deptno = d.deptno
AND e.ename='benoit';
Explained.
SQL> SET LINESIZE 130
SQL> SET PAGESIZE 0
SQL> SELECT * FROM table(DBMS_XPLAN.DISPLAY);
Plan hash value: 3625962092
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 58 | 4 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 1 | 58 | 4 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL | EMP | 1 | 38 | 3 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("E"."ENAME"='benoit')
4 - access("E"."DEPTNO"="D"."DEPTNO")
18 rows selected.
2. DISPLAY_AWR
SQL> SELECT SQL_ID FROM DBA_HIST_SQLTEXT WHERE ROWNUM<=1;
424h0nf7bhqzd
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('424h0nf7bhqzd'));
查看历史查询中包含TOTO的语句的执行计划
SELECT tf.*
FROM DBA_HIST_SQLTEXT ht,
TABLE (DBMS_XPLAN.DISPLAY_AWR (ht.sql_id,
NULL,
NULL,
'ALL')) tf
WHERE ht.sql_text LIKE '%TOTO%';
3.DISPLAY_CURSOR
SQL> CONN SCOTT/tiger
Connected.
SQL> select * from emp where ename='KING';
EMPNO ENAME JOB MGR
---------- ------------------------------ --------------------------- ----------
HIREDATE SAL COMM DEPTNO
------------------- ---------- ---------- ----------
7839 KING PRESIDENT
1981/11/17 00:00:00 5000 10
SQL> set pagesize 200
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 7y29yzz506y9t, child number 0
-------------------------------------
select * from emp where ename='KING'
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|* 1 | TABLE ACCESS FULL| EMP | 1 | 38 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ENAME"='KING')
18 rows selected.
DISPLAY_CURSOR还有很多丰富的用法,我们看看官方文档是怎么描述的。
查看一个具体sql_id的执行计划
SQL> SELECT SQL_ID FROM V$SQLAREA WHERE ROWNUM<=1;
SQL_ID
---------------------------------------
4dy1xm4nxc0gf
SQL> select * from table(dbms_xplan.display_cursor('4dy1xm4nxc0gf',NULL,'ALL ALLSTATS'));
4.DISPLAY_SQL_PLAN_BASELINE
SET LINESIZE 150
SET PAGESIZE 2000
SELECT t.*
FROM (SELECT DISTINCT sql_handle
FROM dba_sql_plan_baselines
WHERE sql_text LIKE '%DEPT%') pb,
TABLE (
DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE (pb.sql_handle, NULL, 'BASIC')) t;