Сравнение производительности между использованием функции Join и Window для получения значений опережения и отставания


11

У меня есть таблица с 20М строк, а каждая строка имеет 3 колонки: time, id, и value. Для каждого idи timeесть valueстатус. Я хочу знать опережающие и запаздывающие значения определенного timeдля конкретного id.

Я использовал два метода для достижения этой цели. Один метод использует соединение, а другой - использование опережающих / запаздывающих оконных функций с кластеризованным индексом timeи id.

Я сравнил производительность этих двух методов по времени выполнения. Метод объединения занимает 16,3 секунды, а метод оконной функции - 20 секунд, не считая времени на создание индекса. Это удивило меня, потому что оконная функция кажется продвинутой, в то время как методы соединения - грубая сила.

Вот код для двух методов:

Создать индекс

create clustered index id_time
 on tab1 (id,time)

Метод соединения

select a1.id,a1.time
   a1.value as value, 
   b1.value as value_lag,
   c1.value as value_lead
into tab2
from tab1 a1
left join tab1 b1
on a1.id = b1.id
and a1.time-1= b1.time
left join tab1 c1
on a1.id = c1.id
and a1.time+1 = c1.time

Статистика ввода-вывода генерируется с использованием SET STATISTICS TIME, IO ON:

Статистика по методу соединения

Вот план выполнения для метода соединения

Метод оконной функции

select id, time, value, 
   lag(value,1) over(partition by id order by id,time) as value_lag,
   lead(value,1) over(partition by id order by id,time) as value_lead
into tab2
from tab1

(Заказ только по timeэкономии 0,5 секунды.)

Вот план выполнения для метода оконной функции

Статистика IO

[Статистика для метода оконной функции 4]


Я проверил данные, sample_orig_month_1999и кажется, что исходные данные хорошо упорядочены по idи time. Это причина разницы в производительности?

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

Мне нравится метод оконной функции из-за лаконичного кода, есть ли способ ускорить его для этой конкретной проблемы?

Я использую SQL Server 2016 в Windows 10 64 бит.

Ответы:


11

Относительно низкая производительность в режиме строк LEADи LAGоконных функций по сравнению с самостоятельными объединениями не является чем-то новым. Например, Майкл Зильберштейн написал об этом на SQLblog.com еще в 2012 году. Существует довольно много накладных расходов в (повторяющихся) операторах сегмента, проекта последовательности, буферизации окна и агрегата потока:

План раздела

В SQL Server 2016 появилась новая опция, которая включает обработку в пакетном режиме для агрегатов окон. Для этого требуется какой-то индекс columnstore для таблицы, даже если он пустой. Наличие индекса columnstore в настоящее время требуется оптимизатору для рассмотрения планов пакетного режима. В частности, он обеспечивает гораздо более эффективный оператор пакетного режима Window Aggregate.

Чтобы проверить это в вашем случае, создайте пустой некластеризованный индекс columnstore:

 -- Empty CS index
CREATE NONCLUSTERED COLUMNSTORE INDEX dummy 
ON dbo.tab1 (id, [time], [value]) 
WHERE id < 0 AND id > 0;

Запрос:

SELECT
    T1.id,
    T1.[time],
    T1.[value],
    value_lag = 
        LAG(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time]),
    value_lead =
        LEAD(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time])
FROM dbo.tab1 AS T1;

Теперь должен дать план выполнения, как:

План магазина рядов в пакетном режиме

... который вполне может выполняться гораздо быстрее

Возможно, вам придется использовать OPTION (MAXDOP 1)ту или иную подсказку, чтобы получить ту же форму плана при сохранении результатов в новой таблице. Параллельная версия плана требует сортировки в пакетном режиме (или, возможно, двух), которая может быть немного медленнее. Это скорее зависит от вашего оборудования.

Для получения дополнительной информации об операторе агрегации окна пакетного режима см. Следующие статьи Ицик Бен-Гана:

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.