WHERE子句中的条件是否会减少其他条件所涵盖的行数?

时间:2017-01-25 12:55:32

标签: sql oracle

假设我有一个函数,POINT_IN_SHAPE('shape_name', x, y)这是一个很昂贵的调用,所以我想减少调用它的次数。防止调用该函数的一种方法是在形状周围绘制一个边界框。例如,如果一个点的x大于形状中的最大x值,那么它就不在里面。

if(x > max_X) return outside;

考虑到这一点,将条件添加到我的WHERE子句会通过减少POINT_IN_SHAPE()需要运行的行数来加快查询速度吗?假设在x的索引中,POINT_IN_SHAPE()不进行边界框检查。

select * from points where x <= max_X and POINT_IN_SHAPE(...);

VS

select * from points where POINT_IN_SHAPE(...);

我希望条件减少其他条件的行集,但我不确定SQL是如何工作的。我也希望能够使用更便宜的条件来减少行数。

我真的不在乎条件的排序是否重要,我只是想知道一个条件是否会减少另一个条件的“搜索空间”。从评论,答案,到其他线程的链接以及一些测试,看起来条件确实减少了where子句中其他条件的搜索空间。

3 个答案:

答案 0 :(得分:2)

在您的示例中,几乎可以肯定优化程序将首先使用条件x <= max_x。为什么?因为某些条件是“访问谓词”(引擎用于确定首先查看哪些行的条件),而其他条件是“过滤谓词”(条件仅用于决定应选择哪些行以及哪些应该是丢弃)。 “访问谓词”在“过滤谓词”之前进行评估(显然,如果你考虑这意味着什么)。

在您的情况下,优化器将决定使用x <= max_x作为访问谓词,尤其是x列上的索引。所以首先使用该条件。

戈登展示了“强制”评估由AND分隔的条件的顺序的标准方法。 (对于由OR分隔的条件,它的工作方式相同。)记住这个技巧,它非常有用 - 即使在这种情况下可能不需要它。如果您的查询更复杂,则可能;例如,如果除了x <= max_x之外,您还有类似state = 'MN'的条件。然后,优化器可以选择使用state = 'MN'作为访问谓词,并将x <= max_x和您的功能条件用作过滤谓词。它仍然可能首先评估不平等,但你可以使用戈登的技巧来确保。

答案 1 :(得分:1)

Oracle不保证条件表达式的排序(没有数据库)。所以,单纯的订购是不够的。使用子查询的情况也是如此 - 如果Oracle认为这样做可以提高效率,那么Oracle保留重新排列表达式的权利。问题是优化器可能是错误的。

这是case子句中where可能合适的情况之一。

where (case when x >= max_x then 'outside'
            when POINT_IN_SHAPE(...) then 'inside'
       end) = 'inside'

case中的条件保证按顺序进行评估。注意:为了清楚起见,这只是使用字符串'inside''outside'

答案 2 :(得分:0)

这取决于数据库引擎执行此查询的方式,执行计划引擎选择的内容。

编写查询的其他方法是首先根据子查询中的条件过滤所需的记录,然后在过滤后的输出上应用函数调用。

在你的情况下,你可以试试这个。

 select POINT_IN_SHAPE('shape_name', x, y) 
    from (select * from points where x <= max_X) data