Является ли это условие сравнения дат SARG-able в SQL?
это условие sargable?
AND DATEDIFF(month,p.PlayerStatusLastTransitionDate,@now) BETWEEN 1 AND 7)
мое правило большого пальца заключается в том, что функция слева делает условие не sargable.. но в некоторых местах я читал, что между пункт sargable. так кто-нибудь знает наверняка?
Для справки:
примечание: если какой-либо гуру заканчивается здесь, пожалуйста, обновите страницу Википедии Sargable. Я немного обновил его, но я уверен, что его можно улучшить больше:)
2 ответов
использование 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());
мы видим большую разницу-последний использует искать:
обратите внимание также, как оценки далеки от вашей версии запроса. Это может быть абсолютно катастрофическим для большого набора данных.
существует очень мало случаев, когда функция или другое выражение, примененное к столбцу, будет sargable. Один случай я знаю CONVERT(DATE, datetime_column)
- но эта конкретная оптимизация недокументирована, и я рекомендую держаться от нее подальше в любом случае. Не только потому, что вы подразумеваете что использование функций / выражений против столбцов в порядке (это не во всех других сценариях), но и потому, что это может привести к потере читает и катастрофические оценки.
Я был бы очень удивлен, если бы это было sargable. Одним из вариантов может быть переписать его как:
WHERE p.PlayerStatusLastTransitionDate >= DATEADD(month,1,CAST(@now AS DATE))
AND p.PlayerStatusLastTransitionDate <= DATEADD(month,7,CAST(@now AS DATE))
который, надеюсь, будет sargable (хотя это не совсем так хороша).