2013-04-04 3 views
0

При чтении при настройке TSQL запросов я видел совет по предотвращению (или осторожности) функций в предложении WHERE. Однако, в некоторых случаях - например, поисковые запросы, требующие динамических дат с сегодняшней даты, - мне любопытно, можно ли еще настроить запрос? Например, запрос ниже этого использует функцию DATEADD для текущей даты, которая позволяет пользователю в любое время, чтобы получить правильную информацию в течение последних тридцати дней:TSQL: Tune Dynamic Query Search

SELECT * 
FROM Zoo..Transportation 
WHERE ArrivalDate BETWEEN DATEADD(DD,-30,GETDATE()) AND GETDATE() 

Если я пытаюсь устранить функцию, DATEADD, Я мог бы объявить переменную, которая будет тянуть это время, а затем запрашивать данные с этого заданного значения, хранящегося в переменной, например:

DECLARE @begin DATE 
SET @begin = DATEADD(DD,-30,GETDATE()) 

SELECT * 
FROM Zoo..Transportation 
WHERE ArrivalDate BETWEEN @begin AND GETDATE() 

Однако план и статистика выполнения показывает точное такое же количество прочтений, сканирование и стоимость партии.

В этих случаях динамические данные (например, с использованием сегодняшней даты в качестве отправной точки), как мы можем уменьшить или исключить использование функций в предложении WHERE?

+0

Что происходит с планом выполнения при изменении второго запроса, чтобы он не использовал GETDATE() в предложении BETWEEN? Вместо этого попробуйте переменную для этого. –

+0

@ Майкл, что не имеет значения. SQL Server достаточно умен, чтобы рассматривать это как константу. –

+0

@MichaelHarmon - я тестировал это, и он генерирует тот же результат, что и Аарон. – Question3CPO

ответ

5

Функции где положение означает делать глупые вещи, как:

WHERE DATEPART(WEEK, ArrivalDate) = 1 

Или

WHERE CONVERT(CHAR(10), ArrivalDate, 101) = '01/01/2012' 

Э.Г. функции против столбцов в предложении where, которое в большинстве случаев уничтожает способность к повышению (другими словами, отрисовка индекса бесполезно и принудительное сканирование индекса или таблицы).

Существует одно исключение, что я знаю:

WHERE CONVERT(DATE, ArrivalDate) = CONVERT(DATE, GETDATE()) 

Но я бы не стал полагаться на это для любого другого сценария.

+0

Так, например, сканирование индекса (в данном случае) означает, что мы оптимизировали, насколько мы можем идти, связанные с способностью (или использованием индекса)? – Question3CPO

+1

Нет, вам обычно понадобится индекс * seek * - сканирование обычно означает, что он должен прочитать весь индекс, чего вы хотите избежать. Теперь, если окажется, что ваше предложение where фактически возвращает большую часть таблицы, сканирование, вероятно, является самым эффективным способом сделать это. Но просто наблюдать за сканированием и вытирать руки и думать, что вы сделали оптимизацию, это неправильный способ подумать об этом. В некоторых случаях это может быть правдой, но каждая ситуация отличается. –

+0

Итак, в этом случае оба запроса возвращают 1000+ строк данных из 90 000+ строк. Чтобы сохранить эти запросы динамическими (и похожими запросами по дате, подобным этим), как мы кодируем, чтобы SQL Server искал эти данные? Я бы предположил, что второй пример подскажет, что SQL Server начнет свое существование, и поэтому ему нужно будет * искать * в этом месте, а затем искать данные после этого местоположения. – Question3CPO

1

IME, используя функции в выражении WHERE, является проблемой только при работе с данными из вашего запроса - это означает, что функция (которая сама по себе может быть сложной SQL) выполняется для каждого значения в вашем запросе - это, вероятно, вызовет сканирование таблицы или подобное, так как optmiser не знает, какой индекс использовать (если есть).

В приведенном выше примере используется DATEADD с текущей датой - значение, вероятно, вычисляется один раз (или если оно рассчитано для каждой строки в вашем результирующем наборе, это не повлияет на план запроса, поскольку он не содержит данных по вашему запросу).