使用 AdventureWorks,如果我们查看这两个等效查询:
SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE DATEDIFF(month,OrderDate,GETDATE()) BETWEEN 1 AND 7;
SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE OrderDate >= DATEADD(MONTH, -7, GETDATE())
AND OrderDate <= DATEADD(MONTH, -1, GETDATE());
在这两种情况下,我们都会看到聚集索引扫描:
但请注意仅在后一个查询中推荐/缺失的索引,因为它是唯一可以从中受益的:
如果我们向 OrderDate 列添加索引,则再次运行查询:
CREATE INDEX dt ON Sales.SalesOrderHeader(OrderDate);
GO
SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE DATEDIFF(month,OrderDate,GETDATE()) BETWEEN 1 AND 7;
SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE OrderDate >= DATEADD(MONTH, -7, GETDATE())
AND OrderDate <= DATEADD(MONTH, -1, GETDATE());
我们看到了很大的不同——后者使用了一个 seek:
还要注意您的查询版本的估计值是如何偏离的。这在大型数据集上绝对是灾难性的。
在极少数情况下,应用于列的函数或其他表达式是可搜索的。我知道的一种情况是CONVERT(DATE, datetime_column) - 但该特定优化没有记录在案,我建议无论如何不要使用它。不仅因为您暗示对列使用函数/表达式是可以的(并非在所有其他情况下都如此),还因为it can lead to wasted reads and disastrous estimates。