2009-01-27 105 views
22

在Sql Server 2005中,当我有多个参数时,我是否保证评估顺序将始终为是从左到右?选择“where子句”评估顺序

使用的一个示例:

select a from table where c=1 and d=2

在该查询中,如果 “C = 1” 状态失败 “d = 2” 条件将永远不会被评估?

PS-“c”是一个整数索引列,d是一个大的varchar和非可索引的列,需要全表扫描

更新我试图避免执行两个查询或条件语句,我只需要这样的:如果“c条件”失败,有一种方法可以避免执行沉重的“d条件”,因为在我的情况下不需要。

回答

26

评估订单不保证。优化器将尝试使用可用信息找到执行查询的最有效方法。

对于你的情况,由于c是索引,而d不是,所以优化器应该查找索引来查找匹配c上谓词的所有行,然后从表数据中检索这些行以评估d上的谓词。

但是,如果它确定c上的索引不是非常有选择性的(尽管在你的例子中没有,性别列很少有用的索引),它可能决定进行表扫描。

要确定执行顺序,您应该为您的查询得到解释计划。但是,要意识到该计划可能会根据优化程序认为的最佳查询而改变。

4

SQL Server将为其执行的每个语句生成一个优化计划。您不必为了获得该收益而订购Where子句。您所拥有的唯一Garuntee是它将按如下顺序运行语句:

SELECT A FROM B WHERE C 
SELECT D FROM E WHERE F 

将在第二行之前运行第一行。

+1

换句话说:NO。 SQL Server会以它认为最快的方式重新排列你的条件。如果你的条件有副作用(可能通过udf函数调用),这可能会导致问题。 – 2009-01-27 16:56:45

+2

将UDF放入WHERE子句可能会非常缓慢。我们或多或少不得不取缔他们的表现如此糟糕。 – Joe 2009-01-27 16:59:57

+0

这不太正确。 – 2009-01-27 17:27:04

2

您可以查看查询的执行计划并确定它实际正在尝试执行的操作。我认为SQL Server的查询引擎应该进行这种类型的扫描,并将其智能地转换为操作。就像,如果你做的“昂贵和虚假”,它会很快评估为假。

从我所学到的,你输入的内容(和可能)与实际执行的不同。你只是告诉服务器你期待什么类型的结果。它如何得到答案并不关联你提供的代码的从左到右。

1

控制评估顺序的一种方法是使用CASE表达式。

[编辑]

流行的观点,我想表达是:

你不能依赖于表达式求值顺序的东西像 “WHERE OR”,因为优化器可能会选择一个计划 评估第一个谓词之前的第二个谓词。但是 CASE语句中表达式的评估顺序是固定的,因此您可以依赖CASE 语句的确定性短路评估。

它确实会有点比下面的网站作为解释更复杂:

http://blogs.msdn.com/b/bartd/archive/2011/03/03/don-t-depend-on-expression-short-circuiting-in-t-sql-not-even-with-case.aspx

2

如果你想确保你可以检查Query Execution Plan。 MSSQL构建/优化的执行计划足够智能,可以在varchar列之前检查索引列。

1

MS SQL Server查询优化器确实会短路,是的。保证。

运行以下命令:

select 1 where 1 = 0 and 1/0 = 10 

它将运行得很好,没有错误,即使你被零除,因为查询优化器将短路评价where子句。这对任何where子句都有影响,你在哪里“and”-ing,其中一个部分是常量。

1

当我们引用的条件只包含文字或常量时,就会完成短路。因此,例如让我们说我们有一个TableA,它有列号为1到10的所有正数,然后如果我写这个查询。

从表A中选择NUM WHERE TableA.num < 0 AND 1/0 = 10。

它会导致错误。

编译器是否足够聪明以确定我的第二个子句是由常量组成的,因此它应该在评估子句之前评估该子句,该子句需要从表或索引进行任何扫描?