TSQL:静态变量与where子句中的计算

时间:2016-08-03 18:53:31

标签: performance tsql sql-server-2012

我正在努力优化一些查询并遇到一个奇怪的问题,我不确定如何解释。使用带有以下代码的SQL Server 2012:

DECLARE @startdate DATETIME2 = DATEADD(day,-1,GETDATE()),
        @enddate DATETIME2 = GETDATE()

SELECT * 
FROM table1 WITH(NOLOCK) 
WHERE somedate BETWEEN DATEADD(day,-1,GETDATE()) AND GETDATE() 
  AND somestate = 'NV'

SELECT * 
FROM table1 WITH(NOLOCK) 
WHERE somedate BETWEEN @startdate AND @enddate 
  AND somestate = 'NV'

查看实际执行计划,第一个选择具有索引查找和键查找,其中第二个选择具有聚簇索引扫描。由于SELECT与功能目的基本相同,我不确定为什么执行计划会有差异。我的上一个DBA告诉我,声明在WHERE子句中使用值的变量比在WHERE子句中进行计算更好,但这似乎与该声明相反。我希望澄清导致这两种说法之间存在巨大差异的原因。我确实试图寻找一些有关这方面的答案,但没有多少运气,如果有人能指出我正确的方向,我会非常感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

我认为你在where子句中使用计算被认为是有害的时会略有误解。使用包含将用于索引的列的计算是在遇到性能问题时,因为它无法有效地对计算执行索引查找。在您的示例中,索引列(somedate)不在计算中,因此它不应对索引产生负面影响。有关SARG的更多说明,请参阅Sql Server Query Performance(WHERE子句中的计算所引用的问题)。

如果您正在查看SSMS中的执行计划,我建议检查它是否建议任何索引,因为第二个计划进行集群扫描而不是搜索会让我觉得您可能需要创建一个更优的索引你的查询。

最后,如果您看到一个Key Lookup,通常表明您的查询未经过优化(Key Lookup Showplan Operator)。

在非性能说明中,Microsoft还建议使用> =< =而不是日期之间以避免意外重叠,但我认为这并不适用于您的情况。

相关问题