暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

oracle 获取执行计划 - EXPLAIN PLAN语句 -2

原创 不吃草的牛_Nick 2023-11-01
191

 

   计划表

计划表是EXPLAIN PLAN语句输出内容写入的地方。如计划表不存在,则会抛出一个错误。默认的计划表归SYS所有,一个名为plan_table的公共同义词将这张表暴露给所有的用户。一旦需要一张私有的计划表,通过utlxplan.sql脚本手工创建是一个不错的实践,脚本可以在$ORACLE_HOME/rdbms/admin目录下找到。如果计划表是手工创建的,一旦执行了数据库升级,不要忘记将计划表删掉并重新创建。实际上,这往往会发生在新版本添加了新属性的时候。

 

有趣的是,默认的计划表是一张会将数据存储直到会话结束的全局临时表(它是一张使用on commit preserve rows选项创建的全局临时表。)。通过这种方式,几个并发的用户可以同时使用它而不互相干扰。

 

要将计划表与EXPLAIN PLAN语句一起使用,至少需要INSERT和select权限。尽管可以不使用DELETE权限执行基本的操作,但最好还是授予该权限。

 

在这里我不会完整地描述计划表,原因很简单:你通常不会直接查询它。关于这张表的列的详细描述,请参考Performance Tuning Guide(11.2及之前的版本),或SQL Tuning Guide(从12.1版本开始)。

 

  查询计划表

很显然,可以直接通过针对计划表发起查询来获取执行计划。但是,使用dbms_xplan包的display函数会简单得多,如接下来的例子所示。可以看到,它的使用非常简单。实际上,为了显示EXPLAIN PLAN语句生成的执行计划,调用这个函数就足够了。注意这个函数返回的值(即一个结果集)是如何通过table函数转换的:

explain plan for select * from emp where deptno = 10 order by ename;

select * from table(dbms_xplan.display);

 

display函数不仅仅限于不带参数的用法。基于这个原因,本章稍后会介绍dbms_xplan包,探索所有的可能性,包括对产生的输出的描述。

 

  绑定变量陷阱

我遇到过的使用EXPLAIN PLAN语句最常见的错误是,指定了一个有别于要分析的语句的SQL语句。当然,那会导致错误的执行计划。因为格式本身对执行计划没有影响,差别通常由替换绑定变量引起。来检查一下接下来的PL/SQL存储过程中查询语句使用的执行计划:

CREATE OR REPLACE PROCEDURE p(p_value IN NUMBER) IS

BEGIN

  FOR i IN (select * FROM emp WHERE empno = p_value)

  LOOP

    NULL;-- do something

  END LOOP;

END;

/

 

常用的技巧是使用字面值替换PL/SQL变量来复制/粘贴查询语句。执行类似这样的SQL语句:

explain plan for select * from emp where empno = 7788;

 

问题是通过使用字面值替换绑定变量,你向查询优化器提交了一条不一样的SQL语句。这种改变可能会对查询优化器做出的决定产生影响。改变是因为SQL概要、存储纲要、SQL计划基线的存在,或者查询优化器用来估算在WHERE子句中使用的谓词选择率的方法(字面值和绑定变量不是按照相同的方式处理的)。

 

正确的途径是使用相同的SQL语句。这是可行的,因为绑定变量可以在EXPLAIN PLAN语句中使用。例如,你应该执行类似的SQL语句(注意,p_value PL/SQL变量被:B1绑定变量替换了,因为PL/SQL引擎也会这么做):

explain plan for select * from emp where empno =:b1;

 

尽管如此,在EXPLAIN PLAN语句中使用绑定变量有两个问题。第一个问题是,默认情况下,绑定变量会被以VARCHAR2类型声明。结果,数据库引擎可能会自动添加一个隐式转换,而那样做会改变执行计划。这点可以通过在dbms_xplan包中的display函数生成的输出的末尾显示的关于谓词的信息来检查。在下面的输出例子中,to_number函数被用于这个目的:

select * from table(dbms_xplan.display);

2 - access("EMPNO"=TO_NUMBER(:B1))

 

通常,检查是否正确处理了数据类型是很好的做法,比如,通过为原始SQL语句中所有不是VARCHAR2类型的绑定变量使用显式转换。

 

第二个问题是在EXPLAIN PLAN语句中使用绑定变量时不会使用绑定变量扫视技术。因为这个问题没有解决方案,所以不能保证通过EXPLAIN PLAN语句生成的执行计划就是运行时会选择的执行计划。换句话说,一旦涉及绑定变量,通过EXPLAIN PLAN语句生成的输出是靠不住的。


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论