【问题标题】:Bind variables results in full table scan in Oracle在 Oracle 中绑定变量导致全表扫描
【发布时间】:2018-04-30 06:23:03
【问题描述】:

在具有 100 万条记录的表上检查查询成本会导致全表扫描,而在 oracle 中使用实际值进行相同查询会导致成本显着降低。

这是 Oracle 的预期行为吗? 有没有办法告诉Oracle不要扫描全表?

使用绑定变量时查询正在扫描整个表:

使用实际变量显着降低查询成本:

【问题讨论】:

    标签: oracle query-optimization performance-testing


    【解决方案1】:

    这是一个分页查询。您想从表中检索少量记录,并根据它们在过滤集中的位置进行过滤。您的投影包括表的所有列,因此您需要查询表以获取整行。问题是,为什么两个查询变体有不同的计划?

    让我们考虑第二个查询。您正在传递偏移量的硬值,因此优化器知道您想要排序集中最近的 11 行。该集合按索引列排序。最重要的元素是优化器知道您需要 11 行。 11 是一百万的一小部分,因此使用索引读取来获取所需的行是一种有效的处理方式。路径从索引的远端开始,读取最后 11 个条目并检索行。

    现在,您的第一个查询具有开始和结束偏移量的绑定变量,以及要返回的行数。这是至关重要的:优化器不知道您是要返回十一行还是一万一千行。所以它选择了一个非常高的基数。其原因是索引读取在检索大量行时表现非常糟糕。全表扫描是处理大块表的最佳方式。

    这是 Oracle 的预期行为吗?

    现在你明白了,你会看到这个问题的答案是是的。优化器根据我们提供的信息做出最佳决策。当我们提供硬值时,它可能非常聪明。当我们提供模糊的数据时,它必须猜测;有时它的猜测不是我们预期的。

    当预期结果集相似时,绑定变量对于运行具有不同值的相同查询非常有用。但是使用绑定变量来指定范围意味着结果集的大小可能会有很大差异。

    有没有办法告诉 Oracle 不要扫描整个表?

    如果您可以修复页面大小,从而删除:a2 参数,那么优化器可以生成更准确的计划。或者,如果您需要在一个小范围内(比如 10 - 100)改变页面大小,那么您可以在查询中尝试 /*+ cardinality (100) */ 提示;只要基数值在正确的数量级内,它就不必是精确值。

    与所有性能问题一样,问题在于细节。因此,您需要对各种性能变化进行基准测试,并为您的特定用例选择最适合的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-01
      • 2013-10-01
      • 2015-12-04
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多