sql - Oracle 在解析 prepared statement 时是否选择了默认的执行计划?

标签 sql database oracle optimization sql-execution-plan

根据这个Oracle documentation ,我可以假设优化器推迟了硬解析并且直到第一次执行准备好的语句时才生成执行计划:

“答案是一种称为绑定(bind)窥视的现象。早些时候,当您在绑定(bind)变量值设置为‘NY’的情况下运行该查询时,优化器必须第一次进行硬解析,同时它会窥视绑定(bind)变量以查看分配给它的值是什么。”

但是当使用绑定(bind)参数为准备好的语句执行 EXPLAIN PLAN 时,我们得到一个执行计划。在他的网站上,Markus Winand说:

“当使用绑定(bind)参数时,优化器没有可用的具体值来确定它们的频率。然后它只是假设一个相等的分布并且总是得到相同的行计数估计和成本值。最后,它总是会选择相同的执行计划。”

哪个是真的?使用均匀分布值模型准备语句时是否生成执行计划,或者硬解析是否推迟到第一次执行时间。

最佳答案

这个讨论遗漏了关于绑定(bind)变量、解析和绑定(bind)窥视的一个非常重要的观点;这是直方图!只有当相关列具有直方图时,绑定(bind)变量才会成为问题。没有直方图,就没有必要查看值。 Oracle 没有关于数据分布的信息,只会使用纯数学(不同的值、空值的数量、行数等)来找到有问题的过滤器的选择性。

绑定(bind)和直方图在逻辑上是相反的。您使用绑定(bind)变量为所有查询获取一个执行计划。您使用直方图为不同的搜索值获取不同的执行计划。 Bind peeking 试图克服这个问题。但它在这方面做得不是很好。许多人实际上将绑定(bind)查看功能描述为“错误”。 Oracle 11g 中出现的自适应游标共享可以更好地解决这个问题。

实际上我看到了很多直方图。我通常禁用直方图(方法 opt=>'for all columns size 1',并且只在我真正需要它们时才创建它们。

然后回到最初的问题:“Oracle 在解析准备好的语句时会选择默认的执行计划吗?” 解析不是一项事件。解析涉及语法检查、语义分析(表和列是否存在,您是否有权访问表)、查询重写(Oracle 可能会以更好的方式重写查询 - 例如 - 如果我们使用过滤器 a=b 和 b =c,那么Oracle就可以加上过滤器a=c),当然也可以找到执行计划。我们实际上区分不同类型的解析——软解析和硬解析。硬解析是 Oracle 还必须为查询创建执行计划的地方。这是一项非常昂贵的事件。

回到问题。解析并不真正关心您是否使用绑定(bind)变量。不同之处在于,如果您使用绑定(bind),您可能只需要进行软解析。使用绑定(bind)变量,您的查询在每次运行时看起来都一样(因此获得相同的 hash_value)。当您运行查询时,Oracle 将检查(在库缓存中)以查看是否已为您的查询准备好执行计划。这不是默认计划,而是一个已经存在的计划,因为其他人已经执行了相同的查询(并让 Oracle 执行硬解析为该查询生成执行计划)并且执行计划尚未从缓存中老化.这不是默认计划。这只是优化器在解析时认为是您的查询的最佳选择的计划。 当您使用 Oracle 12c 时,它实际上变得更加复杂。在 12 Oracle 中有 Adaptive Execution 计划——这意味着执行计划有一个替代方案。它可以从嵌套循环开始,如果它意识到基数估计有误,它可以在查询执行过程中切换到散列连接。它还具有称为自适应统计和 sql 计划指令的东西。所有这些都是为了让优化器和 Oracle 在运行 SQL 时做出更好的选择:-)

关于sql - Oracle 在解析 prepared statement 时是否选择了默认的执行计划?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32883837/

相关文章:

Mysql 检查值是否相同

mysql - (小型)站点是否应该同时使用 SQL 和 noSQL 数据库

java - hibernate 或 oracle 支持时间线?

MySQL选择几个合作伙伴聚合数据的时间序列来绘制图表

sql - 我可以使用LIMIT和OFFSET迭代地获取SELECT查询的结果吗?

非关系型数据库系统

Mysql每日重置次数

sql - 如何获取 Oracle 中同一列中的两个日期之间的差异?

oracle - 如何创建包含对象类型嵌套表的 Oracle 表?

mysql SELECT 超过 1 个或