Sql WHERE子句中的求值顺序和非常慢的查询

Sql WHERE子句中的求值顺序和非常慢的查询,sql,tsql,database-design,Sql,Tsql,Database Design,此查询在>3分钟内执行 SELECT ... WHERE expr1 and expr2 or expr3 or expr4 这会立即终止 我会期待不同的结果,而不是不同的表现。有人能解释为什么吗 Background:select left outer连接了7个表,但它们不是很大(

此查询在>3分钟内执行

SELECT ... WHERE expr1 and expr2 or expr3 or expr4
这会立即终止

我会期待不同的结果,而不是不同的表现。有人能解释为什么吗


Background:select left outer连接了7个表,但它们不是很大(<10k记录了最大的一个),但我强烈建议,这是无法理解的,因为它是从遗留系统上的一个非常旧的工具生成的,而且整个项目很难使用。我只对上面描述的问题感兴趣

第二个版本要求所有记录的
expr1
为真。如果
expr1
只依赖于一个表,那么DBMS甚至可以在执行联接之前进行过滤。(即使它依赖于多个表,至少可以在某些联接之前向下推送。)这可能会减少检查记录的次数,并更好地使用索引。

第二个版本要求所有记录的
expr1
都为true。如果
expr1
只依赖于一个表,那么DBMS甚至可以在执行联接之前进行过滤。(即使它依赖于多个表,也至少可以在某些联接之前向下推送。)这可能会减少检查记录的次数,并更好地使用索引。

比较需要很长时间,因为您需要检查每一条记录的每种可能性

括在括号中,将其视为一组,并允许短路评估

您的第一个查询的计算结果如下:

SELECT ... WHERE expr1 and (expr2 or expr3 or expr4)
检查所有3种情况需要更多的时间


您的第二个计算Expr1,然后可以快速检查子集中的三个条件。我猜其中一个是索引的,可以非常有效地进行检查,这减少了检查其他记录所需的结果集。

比较需要很长时间,因为您需要检查每个记录中的每个可能性

括在括号中,将其视为一组,并允许短路评估

您的第一个查询的计算结果如下:

SELECT ... WHERE expr1 and (expr2 or expr3 or expr4)
检查所有3种情况需要更多的时间



您的第二个计算Expr1,然后可以快速检查子集中的三个条件。我猜其中一个是索引的,可以非常有效地检查,这减少了检查其他的结果集。

查询计划告诉你什么?查询计划告诉你什么?@MartinSmith:不,没有
其中expr1和expr2或expr3或expr4
表示
WHERE(expr1和expr2)或expr3或expr4
:对于给定记录,如果
expr3
为true,即使
expr1
为false,也可以满足要求。因此第二个查询利用
expr1
快速执行,而第一个问题是
expr2
/
expr3
/
expr4
被忽略slow@Raffaele:不完全是。更重要的是,第二个查询利用了一个事实,即
expr1
可以在更早的时候进行计算,因此所需的连接要少得多。第一个问题是,在执行多个联接之后,它需要对多个记录求值
expr1和expr2或expr3或expr4
。从技术上讲,这同样适用于第一个查询,即db可以在联接之前检查e1和e2。在这种情况下,问题在于e3或e4,因为它可以提前计算e1,但必须检查其他表达式以拒绝该表达式record@MartinSmith:不,没有
其中expr1和expr2或expr3或expr4
表示
WHERE(expr1和expr2)或expr3或expr4
:对于给定记录,如果
expr3
为true,即使
expr1
为false,也可以满足要求。因此第二个查询利用
expr1
快速执行,而第一个问题是
expr2
/
expr3
/
expr4
被忽略slow@Raffaele:不完全是。更重要的是,第二个查询利用了一个事实,即
expr1
可以在更早的时候进行计算,因此所需的连接要少得多。第一个问题是,在执行多个联接之后,它需要对多个记录求值
expr1和expr2或expr3或expr4
。从技术上讲,这同样适用于第一个查询,即db可以在联接之前检查e1和e2。在这种情况下,问题出在e3或e4上,因为它可以提前计算e1,但必须检查其他表达式以拒绝我不理解的记录:/expr3和expr4检查得最快,前者应该执行得更快,因为它可以跳过expr1和expr2并直接跳到expr3/expr4。但是我想我不明白你的答案……对不起,第一个查询需要
(expr1和expr2)
或(其他两个查询中的一个)。它
expr1
expr2
可能是单独检查最快的,但另一个很慢,因此第一个查询很慢。由于它们在第二个查询中是分开的,所以可以首先检查“更快”的一个。最终,您会说
expr2
很慢,但在前者中,它总是被计算的(因为Optimizer发现反正
e1和e2
e3
快,比
e4
快)而在后者中,它被跳过,因为
e1
是一个必需条件,并且可以快速计算。对吧?expr2或expr1可能很慢,我不知道是哪个。根据所提供的信息是无法判断的。看起来其中一个比另一个慢得多。第一个查询需要同时检查这两个,第二个查询不需要。也无法知道查询引擎中的求值顺序,因为它们不一定是按顺序进行的。我认为实际上
expr1
必须是更快的一个,因为在第二次查询中它是必需的,因此必须对集合中的每个记录求值。不是吗?我不明白:/If expr3