设为首页 收藏本站
查看: 797|回复: 0

[经验分享] Oracle EXPLAIN PLAN用法

[复制链接]

尚未签到

发表于 2016-7-6 10:31:42 | 显示全部楼层 |阅读模式
1.SQL语句的执行计划
  使用EXPLAIN PLAN语句来确定Oracle数据库下指定SQL语句的执行计划,这个语句插入每一步执行计划的行描述到指定表中。你也可使用EXPLAIN PLAN语句作为SQL跟踪工具的一部分。
  EXPLAIN PLAN命令的语法如下:
  EXPLAIN PLAN
[ SET STATEMENT_ID = string ]
[ INTO [ schema. ] table_name [ @ dblink ] ]
FOR sql_statement ;

  EXPLAIN PLAN的相关选下如下:

  • STATEMENT_ID
  SQL语句的唯一标识符。通过使用SQL语句的标识符,可以向一个计划表中存入多条SQL语句。


  • TABLE_NAME
  存储执行计划的计划表的名称。此表必须已经存在并且与标准表结构一致。如果没有指定计划表名称,EXPLAIN PLAN会尝试使用表名PLAN_TABLE.


  •   SQL_STATEMENT
  你想要知道其执行计划的那条SQL语句。这条SQL语句必须是有效的。并且你也必须有足够的权限来执行它。这条SQL语句可以含有绑定变量。
2.计划表
  默认情况下,Oracle会将执行计划插入如到一张名为PLAN_TABLE的表中。可以使用脚本utlexplain.sql来创建自己的计划表。这个脚本位于Oracle软件安装目录的子目录$ORACLE_HMOE/rmdbs/admin/中。然而,从Oracle 10g开始,Oracle会创建一个全局临时表PLAN_TABLE供所有用户使用,所以通常情况下不需要创建自己的计划表。由于此默认的计划表是一个全局临时表,所以你无法看到其他会话插入的执行计划,你的执行计划也会随着自己会话的结束而自动消失。
  (计划表)
  列名
  类型
  描述
  STATEMENT_ID
  VARCHAR2(30)
  在EXPLAIN PLAN的SET STATEMENT_ID子句提供的SQL语句的唯一标志符。
  PLAN_ID
  NUMBER
  执行计划的在全局表plan_table中的唯一标识符
  TIMESTAMP
  DATE
  EXPLAN PLAN语句执行的日期和时间
  REMARKS
  VARCHAR2(80)
  注释
  OPERATION
  VARCHAR2(30)
  执行的操作类型。如TABLEACCESS,SORT或HASH JOIN
  OPTIONS
  VARCHAR2(225)
  操作的附加信息,例如,以TABLE SCAN为例,选项可能是FULL或BY ROWID
  OBJECT_NODE
  VARCHAR2(128)
  如果是分布式查询,这一列表示用于引用对象的数据库链接名称。如果并行查询,它的值可能对应一个临时的结果集。
  OBJECT_OWNER
  VARCHAR2(30)
  对象的名字
  OBJECT_NAME
  VARCHAR2(30)
  对象名称
  OBJECT_ALIAS
  VARCHAR2(65)
  对象的别名
  OBJECT_INSTANCE
  NUMERIC
  对象在SQL语句中的位置
  OBJECT_TYPE
  VARCHAR2(30)
  对象的类型(表,索引等)
  OPTIMIZER
  VARCHAR2(255)
  解释SQL语句时生效的优化器
  SEARCH_COLUMNS
  NUMBERIC
  未使用
  ID
  NUMERIC
  执行计划的ID号
  PARENT_ID
  NUMERIC
  上一个步骤的ID号
  DEPTH
  NUMERIC
  操作的深度
  POSITION
  NUMERIC
  如果两个步骤有相同的父步骤,有更低POSITION值的步骤将被先执行
  COST
  NUMERIC
  优化器估算出来的此操作的相对成本
  CARDINALITY
  NUMERIC
  优化器预期这一步将饭后的记录数
  BYTES
  NUMERIC
  预计这一步将返回的字节数
  OTHER_TAG
  VARCHAR2(255)
  标识OTHER列中的值的类型。
  PARTITION_START
  VARCHAR2(255)
  访问的分区范围的起始分区
  PARTITION_STOP
  VARCHAR2(255)
  访问的分区范围的结束分区
  PARTITION_ID
  NUMERIC
  计算PARTITION_START和PARTITION_STOP列的值对的ID
  OTHER
  LONG
  对于分布式查询,这列可能是包含发往远程数据库的SQL语句的文本。对于并行查询,它比啊是并行从属进程执行的SQL语句。
  DISTRIBUTION
  VARCHAR2(30)
  描述记录是如何从一组并行查询从属进程分配到后续的“消费者”从属进程的。
  CPU_COST
  NUMERIC
  估算出来的操作的CPU成本
  IO_COST
  NUMERIC
  估算出来的的操作的IO成本
  TEMP_SPACE
  NUMERIC
  估算出来的这一步操作所使用的临时存储的空间大小
  ACCESS_PREDICATES
  VARCHAR2(4000)
  SQL语句中,确定如何在当前步骤中提取记录的子句。
  FILTER_PREDICATES
  VARCHAR2(4000)
  SQL语句中确定对见记录进行过滤的子句路,如WHERE子句在非索引列上的条件。
  PROJECTION
  VARCHAR2(4000)
  决定将返回的记录的子句,通常是SELECT后面的字段列表
  TIME
  NUMBER(20,2)
  优化器为这一步执行估算的时间消耗
  QBLOCK_NAME
  VARCHAR2(30)
  查询块的唯一标识符。
  
  (常见的执行计划操作)
  操 作
  选 项
  描 述
  表的访问路径
  
  
  
  
  
  
  TABLE ACCESS
  FULL
  全表扫描,他会读取表中的每一条记录(严格地说,它读取表的高水位以内的每个数据块)
  CLUSTER
  通过索引簇的键来访问数据
  HASH
  通过散键列来访问表中匹配特定的散列值的一条或多条记录
  BY INDEX ROWID
  通过指定ROWID来访问表中的单条记录。ROWID是访问单条记录的最快捷的方式。通常,ROWID的信息都是有一个相关的索引检索而来
  BY USER ROWID
  通过提供一个绑定变量、字面变量或WHERE CURRENT OF CURSOR子句来通过ROWID进行访问
  BY GLOBAL INDEX ROWID
  通过由全局分区索引获得的ROWID进行访问
  BY LOCAL INDEX ROWID
  通过本地分区索获得的ROWID进行访问
  SAMPLE
  使用SAMPLE子句得到结果集的一个经过采样的子集
  EXTERNAL TABLE ACCESS
  
  访问一张外部表
  RESULT CACHE
  
  这个SQL结果集可能来自结果集缓存
  MAT_VIEW REWIRTE ACCESS
  
  SQL语句被重写以利用物化视图
  索引操作
  ADN_EQUAL
  
  合并来自一个或多个索引扫描的结果集
  INDEX
  UNIQUE SCAN
  只返回一条记录的地址(ROWID)的索引检索
  RANGE SCAN
  返回多条记录的ROWID的索引检索。之所以可以这样返回,是因为是非唯一索引或是使用了区间操作符(例如,>)
  FULL SCAN
  按照索引的顺序扫描整个索引
  KIP SCAN
  搜索碎索引键中哦非前导列的索引扫描
  FULL SCAN(MAX/MIN)
  检索最高或最低的索引条目
  FAST FULL SCAN
  按照块顺序扫描索引的每个条目,可能会使用多块读取
  DOMAIN INDEX
  
  域索引(用户定义的索引类型)检索
  
  
  
  
  
  
  位图操作
  
  
  
  
  
  
  BITMAP
  CONVERSION
  将ROWID转换成位图或将位图转换成ROWID
  INDEX
  从位图中提取一个值或一个范围的值
  MERGE
  合并多个位图
  MINUS
  从一个位图中减去另一个位图
  OR
  按位(bit-wise)对两个位图做OR操作
  表连接
  CONNECT BY
  
  对前一个步骤的输出结果执行一个层次化的自联接操作
  MERGE JOIN
  
  对前一个步骤的输出结果执行一次合并联接
  NESTED LOOPS
  
  对前一个步骤执行嵌套循环联接。对于上层的结果集中的每一行,都会扫描下层的结果集以找到匹配的记录
  HASH JOIN
  
  对两个记录源(row source)进行散列联接
  任何连接操作
  OUTER
  此连接为外联接
  任何连接操作
  ANTI
  此连接为反联接
  任何连接操作
  SEMI
  此连接为半联接
  任何连接操作
  CARTESIAN
  一个结果集中的每一条记录与另一个结果中的每一条记录进行联接
  集合操作
  CONCATENATION
  
  与显示指定一个UNION语句一样,多个结果集被按照同样的方式做合并。它通常会发生在对索引列使用OR语句时
  INTERSECTION
  
  对两个结果集进行比较,只返回在两个结果集中都存在的记录。通常只有显式地使用INTERSECT子句,这个操作才会发生
  MINUS
  
  除在第二个结果中出现过的记录外,返回一个结果中的所有记录。它是使用MINUS集合操作符的结果
  UNION-ALL
  
  对两个结果集进行合并,并返回两个结果集中的所有记录
  UNION
  
  对两个结果集进行合并,并返回两个结果集中的所有记录,但是不返回重复记录
  VIEW
  
  要么访问一个视图定义,要么创建一个临时表来存储结果集
  其他杂项
  FOR UPDATE
  
  由于FOR UPDATE子句的原因,返回的记录都会被锁住
  COLLECTION ITERATOR
  各种
  从一个表函数提取记录的操作(也就是 FROM TABLE())
  FAST DUAL
  
  访问DUAL表,以避免从缓冲区高数缓存中读取
  FILTER
  
  从结果集中排除掉不匹配给定选取条件的记录
  REMOTE
  
  通过数据库链接访问一个外部的数据库
  FIRST ROW
  
  获取查询的第一条记录
  SEQUENCE
  
  使用Oracle序列号生成器来获得一个唯一的序列号
  INLIST ITERATOR
  
  对于IN列表中的每个值都执行一次下一个操作
  LOAD AS SELECT
  
  表示这是一个基于SELECT语句的直接路径INSERT操作
  FIXED TABLE
  
  访问固定的(X$或V$)表
  FIXED INDEX
  
  访问固定表X$上的索引
  WINDOW
  BUFFER
  支持分析函数(如OVER())的内部操作
  WINDOW
  SORT [PUSHED]RANK
  分析函数需要为实现RANK()函数执行一次排序操作
  分区操作
  PARTITION
  SINGLE
  访问单个分区
  ITERATOR
  访问多个分区
  ALL
  访问所有分区
  INLIST
  基于IN列表中的值来访问多个分区
  汇总操作
  COUNT
  
  为了满足COUNT()函数而计算结果集中的记录数
  COUNT
  STOPKEY
  计算结果集中的记录数,当达到一定数量后就停止处理。这通常发生在使用了WHERE子句,并指定了一个最大值ROWNUM(例如,WHERE ROWNUM<=10)的情况下
  BUFFER
  SORT
  对临时结果集做的一次内存排序
  HASH
  GROUP BY
  使用散列操作而不是排序操作实现GROUP BY
  INLIST
  ITERATOR
  对于IN列表中的每个值都实现一次子操作
  SORT
  ORDER BY
  为了满足ORDER BY子句而对结果集进行排序
  AGGREGATE
  当在已经分好组的数据上使用分组函数是会出现此操作
  JOIN
  为了准备合并连接而对记录进行排序
  UNIQUE
  排除重复记录的排序操作,通常是使用DISTINCT子句的结果
  GROUP BY
  为GROUP BY子句对结果集进行排序分组
  GROUP BY NOSORT
  不需要进行排序操作的GROUP BY操作
  GROUP BY ROLLUP
  含有ROLLUP选项的GROUP BY操作
  GROUP BY CUBE
  含有CUBE选项的GROUP BY操作
  
3.查看执行计划
  
当SQL语句的执行计划生成以后,我们就可以去查看SQL语句的执行计划了。有两种方法可以查看执行计划:直接查看计划表和DBMS_XPLAN.DISPALY表函数。

  第一种方法:
  为了更好地理解计划表中的数据,需要针对计划表做层次查询。通过SELECT语句的 CONNECT BY子句对PARENT_ID和ID两列进行自连接。这种查询语句通常的写法如下:
  select rtrim(lpad(' ', 2 * level) || rtrim(operation) || ' ' || rtrim(options)) description,
object_owner,
object_name,
cost,
cardinality,
bytes,
io_cost,
cpu_cost
from plan_table
connect by prior id = parent_id
start with id = 0

  
  第二种方法:
  与手工查询计划表相比,使用DBMS_XPLAN通常可以更好的结果,它的语法更加简单,还提供了多种有用的输出格式,并且可以利用缓存的执行计划统计信息。
  调用DBMS_XPLAN函数最简单的方法就是使用 select * from table()语句,如下面的语句:
  select * from table(dbms_xplan.function(options));
  最常用的两个DBMS_XPLAN函数:
  DBMS_XPLAN.DISPLAY(
table_name IN VARCHAR2 DEFAULT 'PLAN_TABLE',
statement_id IN VARCHAR2 DEFAULT NULL,
format IN VARCHAR2 DEFAULT 'TYPICAL',
filter_preds IN VARCHAR2 DEFAULT NULL);

DBMS_XPLAN.DISPLAY_CURSOR(
sql_id IN VARCHAR2 DEFAULT NULL,
child_number IN NUMBER DEFAULT NULL,
format IN VARCHAR2 DEFAULT 'TYPICAL');

  
4.Examples
  创建emp_test表
  create table emp_test as select *from emp;
  create unique index EMP_TEST_U1 on EMP_TEST (empno);
create index emp_test_n1 on EMP_TEST (ename);

  通过EXPLAIN PLAN语句,插入指定SQL语句的执行计划。
  SQL> explain plan set statement_id ='plan_sql_id' for select * from emp_test t where t.ename='SCOTT';

Explained

  
  手动查询计划表查看计划:
  SQL> select rtrim(lpad(' ', 2 * level) || rtrim(operation) || ' ' || rtrim(options)) description,
2 object_owner,
3 object_name,
4 cost,
5 cardinality,
6 bytes,
7 io_cost,
8 cpu_cost
9 from plan_table
10 connect by prior id = parent_id
11 start with id = 0;

DESCRIPTION OBJECT_OWNER OBJECT_NAME COST CARDINALITY BYTES IO_COST CPU_COST
-------------------------------- ------------- ------------- ------ ----------- ----- ------- ---------
SELECT STATEMENT 2 1 38 2 14733
TABLE ACCESS BY INDEX ROWID SCOTT EMP_TEST 2 1 38 2 14733
INDEX RANGE SCAN SCOTT EMP_TEST_N1 1 1 1 7321

  
  
  调用DBMS_XPLAN函数查看:
  SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1758671844
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 38 | 2 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| EMP_TEST | 1 | 38 | 2 (0)|
|* 2 | INDEX RANGE SCAN | EMP_TEST_N1 | 1 | | 1 (0)|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."ENAME"='SCOTT')

  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-240204-1-1.html 上篇帖子: Oracle 第6章 游标 下篇帖子: oracle事务管理相关问题总结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表