假设我有一个函数,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子句中其他条件的搜索空间。
答案 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