使用dbms_xplan包来获得sql语句的执行计划

dbms_xplan包
dbms_xplan包可以用来显示存储在三个不同地方的执行计划:plan_table表,库缓存和awr.下面将会介绍dbms_xplan包中可用的函数.

输出
这里主要解释通过dbms_xplan包中函数返回的信息.下面是dbms_xplan.display_cursor输出信息的第一部分
SQL_ID 9nrttza3c2x2u, child number 0
————————————-
select * from scott.emp where empno=7788
Plan hash value: 2949544139

在这一部信息中指出与sql语句相关的以下信息:
sql_id识别父游标.这个信息只有当使用display_cursor和display_awr时才有

child number与sql_id一起用来识别子游标.这种信息只有当使用display_cursor时才有

sql语句的文本只有当使用display_cursor和display_awr函数时才有

第二部分显示的是一个表中的执行计划哈希值和执行计划本身:

Plan hash value: 2949544139
--------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |       |       |     1 (100)|
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    38 |     1   (0)| 00:0
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)|
--------------------------------------------------------------------------------

在这个表中,评估和每一操作的执行统计都被提供.这个表中的列数直接取决于可用信息的数量.例如,关于分区的信息,并行处理或执行统计.由于这个原因相同的函数和完全相同的参数可能产生两组不同的输出结果.在这种情况下,你将看一下通常可用的列:
包含执行计划的表中的列如下:
列 描述
id 在执行计划中标识每一个操作.如果在数字的前面有一 个星号.它意味着这一行是谓词信息
operation 被执行操作.也叫做行资源操作
name 被执行操作的对象

查询优化器评估
rows(e-rows) 评估操作所返回的行数
bytes(e-bytes) 评估操作所返回的数据量
TempSpc 评估操作使用的临时表空间大小
cost(%cpu) 评估操作的成本.在括号中指出了cpu成本的百分比.这个值是通过执行计划来计算的.
换句话说,父操作的成本包含了子操作的成本
Time 评估执行这个操作需要的时间(HH:MM:SS)

分区信息
pstart 第一个分区被访问的次数.如果在解析时未知,可以设置为key,key(I),key(mc),key(or)或
kye(sq)

pstop 最后一个分区被访问的次数.如果在解析时未知,可以设置为key,key(I),key(mc),key(or)
或kye(sq)

并行和分布式处理
inst 对于分布式处理,操作使用的数据库链路名称
tq 对于并行处理,在两个并行从属进程之间通信的表队列
in-out 并行或分布式操作之间的关系
pqdistrib 对于并行处理,由生产者使用分布处理将数据返回给消费者

运行时统计
starts 一个特定操作被执行的次数
a-rows 操作返回的实际行数
a-time 操作实际花费的时间(HH:MM:SS)

I/O统计
buffers 在执行时执行的逻辑读取的次数
reads 在执行时执行的物理读取的次数
writes 在执行时执行的物理写的次数

内存利用统计
0Mem 评估一个最优的执行所需要的内存总量
1Mem 评估一次通过执行所需要的内存总量
0/1/m 在最优,一次通过和多次通过模型下被执行的次数

used_mem 在最后一次执行操作时使用的内存量
used_tmp 在最后一次执行操作时使用的临时表空间量.它是以字节为单位

max_tmp 操作中使用临时表空间的最大量
下面的部分显示的是查询块的名字和对象别名:
Query Block Name / Object Alias (identified by operation id):
————————————————————-
1 – SEL$1 / EMP@SEL$1
2 – SEL$1 / EMP@SEL$1
对于执行计划中的每一个操作都会有一个查询与之相关

第四部分只在oracle10gr2中可用,下面显示是在oracle11G中的输出信息.它显示了为了强制特定的执行计划可以设置提示
这种设置提示叫做计划概要

Outline Data
-------------
/*+

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
BEGIN_OUTLINE_DATA
INDEX_RS_ASC(@"SEL$1" "EMP"@"SEL$1" ("EMP"."EMPNO"))
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
DB_VERSION('11.2.0.1')
OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/

下面的部分显示谓词信息
Predicate Information (identified by operation id):
—————————————————
2 – access(“EMPNO”=7788)
Column Projection Information (identified by operation id):
———————————————————–
1 – “EMPNO”[NUMBER,22], “EMP”.”ENAME”[VARCHAR2,10],
“EMP”.”JOB”[VARCHAR2,9], “EMP”.”MGR”[NUMBER,22], “EMP”.”HIREDATE”[DATE,7]
“EMP”.”SAL”[NUMBER,22], “EMP”.”COMM”[NUMBER,22], “EMP”.”DEPTNO”[NUMBER,22

PLAN_TABLE_OUTPUT
——————————————————————————–
2 – “EMP”.ROWID[ROWID,10], “EMPNO”[NUMBER,22]

display函数
display函数返回存储在plan_table表中的执行计划.它返回的是一个实例集合dbms_xplan_type_table.
集合中的元素是实例对象类型dbms_xplan_type.唯一属性的对象类型名叫plan_table_output是varchar2类型
这个函数有以下输出参数:
table_name:指定plan_table表名.缺省值是plan_table如果指定为null将使用缺省值

statement_id:指定sql语句名字是一个可选参数.当执行explain plan语句时.缺省值是null,如果使用缺省值.
那么最近插入到plan_table表中的执行计划会被显示(提供了filter_reds参数但没有指定)

format:指定什么信息被提供在输出信息中.这里有一些原始值(basic,typical,serial,all和advanced).为了
更好的控制有一些额外的修饰符(alias,bytes,cost,note,outline,parallel,partition,peeked_binds,
predicate,projection,remote和rows)可以被加到参数中.如果信息需要被添加可以通过字符+做为可选的修饰符
例如(basic+predicate).如果信息要被删除可以通过字符-做为可选的修饰符(例如,typical-bytes).多个修饰符
可以同时被指定例如(typical+alias-bytes-cost).缺省值是typical,原始值advanced和可用的修饰符只在
oracle10gr2中有.

filter_preds:当查询plan_table表时应用一个限制.这个限制是基于plan table表中某一列的一个常规sql谓词(
例如statement_id=’test’).缺省值是null.如果使用缺省值,那么最近插入plan_table表中的执行计划将会被显示.
这个参数只能在oracle10gr2中使用.

为了使用display函数,调用都只需要有dbms_xplan包的execute权限和plan_table表的select权限

格式参数的原始值表
值 描述
basic 只会显示最小量的信息,基本只有操作和被执行的对象的信息

typical 显示最相关的信息,除以别名,计划概要和列投影信息以外的信息

serial 象typical只有并行处理的信息不显示

all 显示了除了计划概要以外的所有信息

advanced 显示所有可用的信息

236

格式参数可以使用的修饰符
值 描述
alias 控制显示的查询块名字和对象别名
bytes 控制在执行计划表中列bytes的显示
cost 控制在执行计划表中列cost的显示
note 控制注释的显示
outline 控制概要的显示
parallel 控制并行处理信息的显示特别是执行计划表中的TQ,IN-OUT和PQ Distrib列的显示
partition 控制分区信息的显示特别是执行计划表中的Pstart和Pstop列的显示
peeked_binds 控制窥视绑定变量的显示
predicate 控制过滤和访问谓词的显示
projection 控制列投影信息的显示
remote 控制远程执行sql语句的显示
rows 控制执行计划表中的rows列的显示

下面的查询将显示使用不同的格式参数值basic,typical和advanced来显示执行计划.

SQL> explain plan for select * from scott.emp where empno=7788;

Explained

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2949544139
----------------------------------------------
| Id  | Operation                   | Name   |
----------------------------------------------
|   0 | SELECT STATEMENT            |        |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |
|   2 |   INDEX UNIQUE SCAN         | PK_EMP |
----------------------------------------------

9 rows selected

SQL> SELECT * FROM table(dbms_xplan.display(NULL,NULL,'typical'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2949544139
--------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    38 |     1   (0)| 00:0
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    38 |     1   (0)| 00:0
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:0
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPNO"=7788)

14 rows selected

SQL> SELECT * FROM table(dbms_xplan.display(NULL,NULL,'advanced'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2949544139
--------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    38 |     1   (0)| 00:0
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    38 |     1   (0)| 00:0
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:0
--------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / EMP@SEL$1
   2 - SEL$1 / EMP@SEL$1
Outline Data
-------------
  /*+

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
      BEGIN_OUTLINE_DATA
      INDEX_RS_ASC(@"SEL$1" "EMP"@"SEL$1" ("EMP"."EMPNO"))
      OUTLINE_LEAF(@"SEL$1")
      ALL_ROWS
      DB_VERSION('11.2.0.1')
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPNO"=7788)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
   1 - "EMPNO"[NUMBER,22], "EMP"."ENAME"[VARCHAR2,10],
       "EMP"."JOB"[VARCHAR2,9], "EMP"."MGR"[NUMBER,22], "EMP"."HIREDATE"[DATE,7]
       "EMP"."SAL"[NUMBER,22], "EMP"."COMM"[NUMBER,22], "EMP"."DEPTNO"[NUMBER,22

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   2 - "EMP".ROWID[ROWID,10], "EMPNO"[NUMBER,22]

42 rows selected

下面的查询将显示使用格式化参数basic和typical并使用修饰符来增加或删除所要输出的信息.

SQL> SELECT * FROM table(dbms_xplan.display(NULL,NULL,'basic +predicate',NULL));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2949544139
----------------------------------------------
| Id  | Operation                   | Name   |
----------------------------------------------
|   0 | SELECT STATEMENT            |        |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |
----------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPNO"=7788)

14 rows selected

SQL>
SQL> SELECT * FROM table(dbms_xplan.display(NULL,NULL,'typical -bytes -note',NULL));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2949544139
------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |     0   (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPNO"=7788)

14 rows selected

display_cursor函数
display_cursor函数用来显示存储在库缓存中的执行计划.在oracle10g中可以使用,和display一样它返回也是实例集合
dbms_xplan_type_table.这个函数有以下输入参数:
sql_id:指定要被返回的执行计划的父游标.缺省值是null,如果使用缺省值会显示当前会话最后一次执行的sql语句的
执行计划

cursor_child_no:指定子游标号与sql_id一起用来识别被返回的执行计划的子游标.缺省值是0,如果指定为null,那么通过
sql_id找到的父游标的所有子游标

format:指定哪些信息被显示.这个参数与display的格式化参数一样.如果执行统计可用(换句话说,如查初始化参数
statistics_level设置为all或在sql语句中指定gather_plan_statistics提示),那么也支持修饰符.它的缺省值为
typical

为了使用display_cursor函数,调用都要对以下动态性能视图v$session,v$sql,v$sql_plan和v$sql_plan_statistics_all
有select权限.而select_catalog_role角色和select any dictionary系统权限提供了这些权限

格式化可以使用的修饰符
值 描述
allstats* 这是一个对于iostats,memstats的一个快捷方式
iostats* 控制I/O统计的显示
last* 默认是所有执行的累积统计被显示如果这个值被指定只有最后的执行统计被显示
memstats* 控制PGA相关统计的显示
runstats_last 和iostats last一样,它只能在oracle10gr1中使用
runstats_tot 和iostats一样,只能在oracle10gr1中使用

下面的例子显示在查询语句中使用gather_plan_statistics来生成执行计划.display_cursor函数针显示最后执行的
I/O统计.注意这里只会显示逻辑读取操作(buffers)因为这里没有物理读或写:

SQL> select /*+ gather_plan_statistics */ * from scott.emp where empno=7788;

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
 7788 SCOTT      ANALYST    7566 1987-4-19     3000.00               20

SQL> select a.SQL_TEXT,a.SQL_ID from v$sqlarea a where a.SQL_TEXT
  2  like '% select /*+ gather_plan_statistics */ * from scott.emp where empno=7788 %' and a.sql_text not like  '%v$sqlarea%'
  3  ;

SQL_TEXT                                                                         SQL_ID
-------------------------------------------------------------------------------- -------------
 select /*+ gather_plan_statistics */ * from scott.emp where empno=7788          dzbmswjhdhk8t




SQL> SELECT * FROM table(dbms_xplan.display_cursor('dzbmswjhdhk8t',0, 'iostats last'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  dzbmswjhdhk8t, child number 0
-------------------------------------
 select /*+ gather_plan_statistics */ * from scott.emp where empno=7788
Plan hash value: 2949544139
--------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Starts | E-Rows | A-Rows |   A-Ti
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |      1 |        |      1 |00:00:0
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |      1 |      1 |      1 |00:00:0
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |      1 |      1 |      1 |00:00:0
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPNO"=7788)

19 rows selected

display_awr函数
这个函数返回存储在awr中的执行计划.在oracle10g中可以使用.和display函数一样,它返回的也是一个实例集合
dbms_xplan_type_table.这个函数有以下输入参数:
sql_id:指定要被返回执行计划的父游标.这个参数没有缺省值

plan_hash_value:指定要被返回执行计划的哈希值.缺省值是null.如果使用缺省值,与通过sql_id标识的父游标相关的
所有执行计划都会被返回

db_id:指定要返回哪个数据库的执行计划,这个参数的缺省值是null,如果使用缺省值就代表是当前数据库

format:指定哪些信息会被显示.与display的格式化参数相同,缺省值是typical

为了能使用display_awr函数,调用者至少要对以下视图dba_hist_sql_plan和dbs_hist_sqltext有select权限.
如果db_id参数没有指定,那么对v$database视图要有select权限.select_catalog_role角色提供了这些权限.

当对于一个特定的游标有多个执行计划存在时使用plan_hash_value参数进行查询是有帮助的

SQL> SELECT * FROM table(dbms_xplan.display_awr('4pqx4cy7p7tnp',2657262937,NULL,'basic'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 4pqx4cy7p7tnp
--------------------
select * from v$sql_plan
Plan hash value: 2657262937
--------------------------------------
| Id  | Operation        | Name      |
--------------------------------------
|   0 | SELECT STATEMENT |           |
|   1 |  FIXED TABLE FULL| X$KQLFXPL |
--------------------------------------

13 rows selected

有很多情况导致一个游标有多个执行计划.比如象增加了一个索引或都数据发生变化(对象统计改变).基本上查询优化器的工作环境随时发生变化所以可能会生成不同的执行计划.因此当一个sql语句执行比较长的时间又没有报错你对这个语句的性能产生怀疑的时候输出的执行计划的信息对于诊断性能问题是有帮助的.如果在这种情况下,你可以基于输出的信息推断出导致问题的原因.

发表评论

电子邮件地址不会被公开。