Является ли это условие сравнения дат 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());

В обоих случаях мы видим кластеризованный индекс сканирования:

enter image description here

но обратите внимание на рекомендуемый / отсутствующий индекс только на последнем запросе, так как это единственный, который может извлечь из него выгоду:

enter image description here

если мы добавим индекс в столбец 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());

мы видим большую разницу-последний использует искать:

enter image description here

enter image description here

обратите внимание также, как оценки далеки от вашей версии запроса. Это может быть абсолютно катастрофическим для большого набора данных.

существует очень мало случаев, когда функция или другое выражение, примененное к столбцу, будет 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 (хотя это не совсем так хороша).