DBMS_XPLAN.DISPLAY_CURSOR 中的 SQL 计划差异

标签 sql oracle explain

在 Oracle 12.1 上运行,我正在寻找计划中包含全表扫描的 SQL。
当我查看时:

select * from V$SQL_PLAN where sql_id = '89p47f9wnnwg9'

enter image description here

我返回了 21 行,其中一行的表访问权限为 FULL

但是,如果我为相同的 sql _id 调用此方法:

SELECT * FROM TABLE ( DBMS_XPLAN.DISPLAY_CURSOR ('89p47f9wnnwg9', 0, 'ALL'))

我得到的结果只有计划表中的 13 行,并且缺少 TABLE ACCESS FULL。

enter image description here

为什么会出现这种差异?

最佳答案

一个查询字符串(由 SQL_ID 表示)可以有多个不同的执行计划。所有内容都存储在 V$SQL_PLAN 中,并由不同的 CHILD_NUMBER 标识。

函数DBMS_XPLAN.DISPLAY_CURSOR有第二个参数,您可以在其中传递所需的 child_number。如果省略第二个参数,该函数将返回所有子游标,因此实际上您应该看到 V$SQL_PLAN 中的所有行(但在不同的执行计划中)。

要查看实际使用的是哪个子游标,您可以检查V$SESSIONSQL_CHILD_NUMBER

12c 更新

这是对为什么 V$SQL_PLAN 的行数比 DBMS_XPLAN.DISPLAY_CURSOR 更多的问题的明显答案 在 Oracle 12c 版本之前,这是最有可能的一种。 12c介绍Adaptive Query Optimization 其中某些操作被优化器标记为不活动。这个选择可以通过执行引擎来切换。 此类计划可以通过操作STATISTICS COLLECTOR来识别。 STATISTICS COLLECTOR 在执行时测试实际行数 如果它高于优化计算的拐点,则切换计划。 (例如 - 嵌套循环对于几行工作正常,但是 对于大量来说,它是“悬挂”的;相反的散列连接适用于大量行,但对于少量行,它的开销很高。 拐点应该对应于这样的行数,其中成本估计相同)。

不幸的是,V$SQL_PLAN 中没有列标识非事件操作。

这个blog观察发现,可以使用元素 display_map 属性 @skp

OTHER_XML 列中提取此信息
 <display_map>
    <row op="1" dis="1" par="0" prt="0" dep="1" skp="0"/>
    <row op="2" dis="2" par="1" prt="0" dep="2" skp="0"/>
    <row op="3" dis="2" par="2" prt="0" dep="2" skp="1"/>
    ....

关于DBMS_XPLAN.DISPLAY_CURSOR 中的 SQL 计划差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48583868/

相关文章:

sql - 解释 - 只插入一行

sql - 如何将 base-2 字符串(例如 '001011' )转换为二进制数据类型?

sql - 为什么 OS X 会终止在终端中立即执行的进程?

database - OALL8 在 Oracle Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production 中处于不一致状态

mysql - LEFT JOIN 比 INNER JOIN 快得多

mongodb - pymongo 聚合不允许解释选项

c# - 计算连续休假天数,跳过节假日和周末

c# - sql 选择顶部 X 到 X+N

oracle - 物化 View 创建速度很快,但刷新需要几个小时

sql - 从 ORACLE 数据库中选择记录