Если вы не разобрались в тонкостях работы базы данных, то использование новых средств языка T-SQL может привести к неожиданным результатам в плане производительности.
Я уже писал о том, как подходить к работе с датами в WHERE: Where To Do Date Math In Your Where Clause.
Но оказалось, что все то же самое справедливо для обработки часовых поясов.
Для начала создадим индекс:
CREATE INDEX c ON dbo.Comments(CreationDate);
Теперь представим, что нам нужно сделать запрос к таблице Comments с учетом часового пояса:
DECLARE @d datetime = '20131201';
SELECT
COUNT_BIG(*) AS records
FROM dbo.Comments AS c
WHERE c.CreationDate AT TIME ZONE 'UTC+12' >= @d
OPTION(RECOMPILE);
GO
Ждать мы будем долго. Я полагаю, что минута для вас — это долго. Для меня это так, потому что каждая минута ожидания — это время, когда я не занимаюсь чем-то более полезным.
Мы написали плохой запрос. Проблема здесь в том, что мы пытаемся преобразовать значение в каждой строке таблицы в новый часовой пояс, а затем сравнить со значением, которое мы могли бы очень легко вычислить один раз и сравнить с CreationDate
.
DECLARE @d datetime = '20131201';
SELECT
COUNT_BIG(*) AS records
FROM dbo.Comments AS c
WHERE c.CreationDate >= DATEADD(HOUR, 1, @d) AT TIME ZONE 'UTC-11'
OPTION(RECOMPILE);
GO
Теперь запрос выполняется гораздо быстрее.
Кто-то может сказать, что мы обманули время, если посмотреть, насколько быстрее все стало работать, даже без помощи параллелизма.
На эту тему есть довольно много постов не так ли? Но важно помнить — вопрос не в том, что в условии находится слева, а что справа. Главное — что мы вычисляем:
Если данные (то, что мы храним физически) — их преобразование превращается в цирк.
Если значение (то, что мы вычисляем один раз через параметр, переменную или иным способом) — это гораздо меньшая нагрузка.
Завтра состоится открытое занятие, на котором поговорим о том, что нового появилось в SQL Server 2022. Обсудим, как новые фичи упростят жизнь разработчикам и DBA. Регистрация открыта по ссылке для всех желающих.
Комментарии (2)
Akina
26.12.2022 14:15+1Лучше было бы сразу отправить читать справку по термину SAGRable, а не рассматривать один частный случай.
akakoychenko
Эх... Помню, надо было джойнить по сложному условию со сравнением времен две огромные таблицы фактов с разными таймзонами за достаточно большой период времени, чтобы попасть на летне-зимнюю смену пояса, и когда увидел, что 160 ядер загружены, а прогресса нет, и выяснил причину, то вышло выкрутиться костылем. Сначала с точностью до часа сгрупировал все уникальные таймстампы, потом для каждой строки приджойнил назад на эту cte, вычислил смещение в часах, и после этого через dateadd получил приведенное время. Перф вырос раз в 10 или 100.
Вообще, невероятно странно, что настолько ущербную особенность работы допустили в M$. По сути, для каждой отдельной строки происходит вызов к API операционной системы. Но, даже, если часок посидеть с ручкой и блокнотом, то можно придумать алгоритм, который покроет все возможные кейсы смен поясов, и при этом снизит количество вызовов на порядки.