绑定变量会导致Oracle中的全表扫描

时间:2018-04-30 06:23:03

标签: oracle query-optimization performance-testing

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

这是甲骨文的预期行为吗? 有没有办法告诉Oracle不要扫描整个表?

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

The query is scanning the full table when bind variables are used

查询成本会因实际变量而显着降低:

The query cost reduces significantly with actual variables

1 个答案:

答案 0 :(得分:2)

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

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

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

  

这是甲骨文的预期行为吗?

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

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

  

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

如果您可以修复pagesize,那么删除:a2参数,这将允许优化器生成更准确的计划。或者,如果您需要在较小范围内(例如10 - 100)更改页面大小,那么您可以在查询中尝试/*+ cardinality (100) */提示;如果基数值在正确的数量级内,则不必是精确值。

与所有表演问题一样,魔鬼也在具体。因此,您需要对各种性能变化进行基准测试,并选择最适合您特定用例的内容。