Sql WHERE子句中的求值顺序和非常慢的查询
此查询在>3分钟内执行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个表,但它们不是很大(
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