2010-03-30 2 views
4

Я пытаюсь оптимизировать некоторые ужасно сложные SQL-запросы, потому что требуется слишком много времени для завершения.Является ли SQL DATEDIFF (год, ..., ...) дорогим вычислением?

В моих запросах у меня есть динамически создаваемые операторы SQL с множеством одинаковых функций, поэтому я создал временную таблицу, где каждая функция вызывается только один раз, а не много, много раз - это сокращает время выполнения на 3/4 ,

Итак, мой вопрос: могу ли я ожидать увидеть большую часть разницы, если скажем, 1000 датированных вычислений сужаются до 100?

EDIT: Запрос выглядит следующим образом:

SELECT DISTINCT M.MID, M.RE FROM #TEMP INNER JOIN M ON #TEMP.MID=M.MID 
WHERE (#TEMP.Property1=1) AND 
DATEDIFF(year, M.DOB, @date2) >= 15 AND DATEDIFF(year, M.DOB, @date2) <= 17 

, где они генерируются динамически в виде строк (скомпоновать в биты и куски), а затем выполняется так, что различные параметры могут быть изменены по каждой итерации - в основном последние строки, содержащие все виды запросов DATEDIFF.

Существует около 420 таких запросов, в которых эти датированные оценки вычисляются так. Я знаю, что я могу легко собрать их всех в темп-таблицу (1000 датфиксов - 50) - но стоит ли это, будет ли разница в секундах? Я надеюсь на улучшение лучше, чем на десятые секунды.

+3

Опубликовать запрос - на самом деле не поможет вам подтвердить свои предположения при выполнении DATEDIFF в глубинных подзапросах 2+ ... –

ответ

13

Это зависит от того, что вы делаете, чтобы быть честным относительно степени удара производительности.

Например, если вы используете DATEDIFF (или любую другую функцию) в предложении WHERE, это будет причиной более низкой производительности, поскольку это предотвратит использование индекса в этом столбце.

например. базовый пример, поиск всех записей в 2009 году

WHERE DATEDIFF(yyyy, DateColumn, '2009-01-01') = 0 

не будет использовать индекс в DateColumn. В то время как лучшее решение, обеспечивая оптимальное использование индекса будет:

WHERE DateColumn >= '2009-01-01' AND DateColumn < '2010-01-01' 

Я recently blogged о разнице это делает (с показателями эффективности/сравнениях план выполнения), если вы заинтересованы.

Это было бы дороже, чем возвращение DATEDIFF в качестве столбца в наборе результатов.

Я бы начал с определения отдельных запросов, которые занимают больше всего времени. Проверьте планы выполнения, чтобы увидеть, где проблема, и настройтесь оттуда.

Edit: Основываясь на примере запроса вы дали, вот подход вы можете попробовать, чтобы удалить использование DATEDIFF в ИНЕКЕ. Основной пример, чтобы найти всех, кому было 10 лет, на определенную дату - I думаю, Математика правильная, но вы все равно получите идею! Дал ему быстрый тест, и кажется прекрасным. Должно быть достаточно легко адаптироваться к вашему сценарию. Если вы хотите найти людей между (например,) 15 и 17 годами на определенную дату, то это также возможно при таком подходе.

-- Assuming @Date2 is set to the date at which you want to calculate someone's age 
DECLARE @AgeAtDate INTEGER 
SET @AgeAtDate = 10 

DECLARE @BornFrom DATETIME 
DECLARE @BornUntil DATETIME 
SELECT @BornFrom = DATEADD(yyyy, -(@AgeAtDate + 1), @Date2) 
SELECT @BornUntil = DATEADD(yyyy, [email protected] , @Date2) 

SELECT DOB 
FROM YourTable 
WHERE DOB > @BornFrom AND DOB <= @BornUntil 

Важное примечание, которое следует добавить, касается возраста, которое можно использовать с ДОБ, этот подход является более точным. В вашей текущей реализации учитывается только год рождения, а не фактический день (например,кто-то родился 1 декабря 2009 года, будет показан как 1 год от 1 января 2010 года, когда они не будут 1 до 1 декабря 2010 года).

Надеюсь, это поможет.

+2

Исправить, и, конечно, это относится к почти * любой * функции, используемой для обертывания индексированного столбца , а не просто 'DATEDIFF'. – Aaronaught

+0

@Aaronaught - да, спасибо за улов. Я обновил свой ответ, чтобы сделать это более ясным – AdaTheDev

+0

Да, хороший ответ – HLGEM

0

DATEDIFF довольно эффективен по сравнению с другими методами обработки значений даты и времени, например строк. (see this SO answer).

В этом случае это звучит так, будто вы перебираете одни и те же данные, что, вероятно, дороже, чем при использовании временной таблицы. Например, статистика будет сгенерирована.

0

Одна вещь, которую вы могли бы сделать для повышения производительности, может заключаться в том, чтобы поместить индекс в таблицу temp на MID.

Проверьте план выполнения, чтобы узнать, помогает ли он (может зависеть от количества строк в таблице temp).

Смежные вопросы