2009-02-12 88 views
0

假设我有这样一个SQL语句在代码的某处先前设置的变量@FOO如下:查询优化TSQL否则

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO OR @FOO IS NULL) 

是查询优化器足够聪明,做OR的第二面第一个(@FOO IS NULL)是因为(另一个假设)执行空检查比执行字段比较更快?

我已经做了一些非正式的基准测试,不仅我看不出有什么区别,而且在我的尝试中得到了不同的结果时间,这导致了进行适当比较的能力。

+0

你确定你需要用你的时间来处理那些事吗? 看看卢克关于SQL是什么和不是什么的答案... 并尝试更广泛地审视这个问题:如果这样一个简单的查询对您来说是一个问题,那么您可能称它为太多次... – siukurnin 2009-02-13 10:31:14

+0

漂亮当然他只是用这个作为一个理论的例子来证明他的观点/问题,那就是你是否可以在SQL优化器中使用带变量的查询...... – 2013-10-02 18:41:49

回答

3

简短的答案...

,优化器是足够聪明。

较长的答案...

SQL是声明,而不是命令式:您的查询的条件的描述,你的结果必须符合,它是一步一步如何产生的说明那些结果。

优化程序以最有效的顺序执行查询。它不保证以任何特定的顺序评估你的子句,甚至根本不评估它 - 如果能够在不评估特定子句的情况下得到正确的结果,那么为什么它会受到影响?

任何特定查询的实际评估顺序都是一个实现细节,并且可以随时间变化(例如,随着表上的统计信息的变化)。

在实践中,优化器偶尔会出错,但在这种特殊情况下 - 将变量与NULL或从表或索引读取进行比较 - 我认为它没有太大的可能性,尽管您可能会想要consider using OPTION(RECOMPILE) or OPTION(OPTIMIZE FOR ...)

0

它足够聪明,先应用更快的条件,假设它可以判断在一般情况下哪种比较更快。在这种情况下,NULL检查几乎总是比较快,因为它必须比较表达式的每一边最多一个字节,并且可以将它分解出来。

1

试着用相反的顺序条款测试它:

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL OR FIELD = @FOO) 

您可能会发现第一个测试短路第二,而不是相反。

+0

是的,这是我的想法,但它可能取决于实现。 – 2009-02-12 18:18:07

0

如果此查询位于存储过程中,可能在此处起作用的一个因素是“参数嗅探”。这可能会导致查询响应时间不一致。为了解决这个问题,在你的sproc中声明一个内部变量,并将这个变量赋值给参数值,然后在你的where子句中使用内部变量,或者在你的存储过程中使用RECOMPILE子句。关于这个问题有很多链接。

1

根据我的经验,有时使用两个查询和一个“UNION”而不是“OR”子句的速度会更快。

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO) 

UNION 

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL) 

该方法的缺点是重复SELECT语句,但性能提高1500%是正确的。当然,这取决于数据库结构(在我的情况下它很糟糕,我无法改变它)。