Используя 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());
Мы видим большую разницу - последний использует поиск:
Также обратите внимание на то, что оценки для вашей версии запроса сильно отличаются. Это может иметь катастрофические последствия для большого набора данных.
В очень редких случаях функция или другое выражение, примененное к столбцу, будет саргируемым. Один случай, о котором я знаю, - это CONVERT(DATE, datetime_column)
, но эта конкретная оптимизация недокументирована, и я все равно рекомендую держаться подальше от нее. Не только потому, что вы неявно предполагаете, что использование функций / выражений для столбцов - это нормально (это не во всех других сценариях), но и потому, что это может привести к потере чтения и катастрофическим оценкам.
person
Aaron Bertrand
schedule
01.06.2012