SQL Datefiff (год,…,…) дорогостоящим вычислением?
-
23-09-2019 - |
Вопрос
Я пытаюсь оптимизировать некоторые ужасно сложные запросы SQL, потому что это займет слишком много времени, чтобы закончить.
В своих вопросах я динамически создал операторы SQL с множеством одинаковых функций, поэтому я создал временную таблицу, в которой каждая функция называется только один раз, а не много, много раз - это сокращало мое время выполнения на 3/4.
Итак, мой вопрос: могу ли я ожидать большую часть разницы, если скажем, 1000 вычислений с датифу сужаются до 100?
РЕДАКТИРОВАТЬ: Запрос выглядит так:
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
где они генерируются динамически в виде строк (составляемых в биты и кусочки), а затем выполняются так, чтобы различные параметры могли быть изменены вдоль каждой итерации - в основном последние строки, содержащие всевозможные задачи датифы.
Есть около 420 подобных запросов, где эти датифы рассчитываются так. Я знаю, что я могу легко потянуть их в таблицу температуры (1000 устаревших до 50) - но стоит ли это, будет ли это иметь какое -либо значение в секундах? Я надеюсь на улучшение лучше, чем в десятые секунды.
Решение
Это зависит от того, что вы делаете, чтобы быть честным в отношении степени удара.
Например, если вы используете датиф (или действительно любую другую функцию) в предложении, где это будет причиной более низкой производительности, поскольку он предотвратит использование индекса в этом столбце.
Например, базовый пример, поиск всех записей в 2009 году
WHERE DATEDIFF(yyyy, DateColumn, '2009-01-01') = 0
Не будет хорошо использовать индекс на DateColumn. Принимая во внимание, что лучшее решение, обеспечение оптимального использования индекса было бы:
WHERE DateColumn >= '2009-01-01' AND DateColumn < '2010-01-01'
я Недавно включил в блог О разнице, которое это делает (с сравнением статистики статистики/выполнения), если вам интересно.
Это было бы дороже, чем, скажем, возвращение датифа в качестве колонки в результате.
Я бы начал с определения отдельных запросов, которые занимают больше всего времени. Проверьте планы выполнения, чтобы увидеть, где проблема лежит, и оттуда настройте.
Редактировать:Основываясь на примере запроса, который вы дали, вот подход, который вы можете попытаться удалить использование датифа в пункте «Где. Основной пример, чтобы найти всех, кому было 10 лет в данную дату - я считать Математика верна, но вы все равно получаете идею! Дал ему быстрый тест, и кажется в порядке. Должно быть достаточно легко, чтобы адаптироваться к вашему сценарию. Если вы хотите найти людей между (например) 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, -@AgeAtDate , @Date2)
SELECT DOB
FROM YourTable
WHERE DOB > @BornFrom AND DOB <= @BornUntil
Важным примечанием для добавления является возрастные какуляции из DOB, этот подход более точен. Ваша текущая реализация учитывает только год рождения, а не фактический день (например, кто -то, родившийся 1 декабря 2009 года, покажет, что он будет 1 год 1 января 2010 года, когда он не 1 до 1 декабря 2010 года).
Надеюсь это поможет.
Другие советы
Datediff довольно эффективен по сравнению с другими методами обработки значений DateTime, таких как строки. (Смотрите это так ответь).
В этом случае это звучит так, как будто вы переходите снова и более те же данные, что, вероятно, дороже, чем использование таблицы температуры. Например, статистика будет создана.
Одна вещь, которую вы могли бы сделать, чтобы улучшить производительность, заключается в том, чтобы поставить индекс на таблицу температуры в середине.
Проверьте свой план выполнения, чтобы увидеть, может ли это зависеть от количества строк в таблице температуры).