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


11

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

Для цього я використав два методи. Один метод - це використання join, а інший метод - використання віконних функцій lead / lag з кластерним індексом на 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

Статистика IO, сформована за допомогою 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 секунди.)

Ось план виконання методу функції Windows

Статистика ІО

[Статистика методу функції вікна 4]


Я перевірив дані в, sample_orig_month_1999і здається, що необроблені дані добре впорядковані idі time. Це причина різниці у виконанні?

Здається, що метод з'єднання має більше логічних зчитувань, ніж метод віконної функції, тоді як часу виконання для першого фактично менше. Це тому, що перший має кращий паралелізм?

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

Я використовую SQL Server 2016 у Windows 10 64 біт.

Відповіді:


11

Відносно низька продуктивність функцій вікон LEADта LAGфункцій вікон у порівнянні з функцією самостійного приєднання не є новим. Наприклад, Майкл Зільберштейн писав про це на SQLblog.com ще у 2012 році. У операторів (повторних) сегментів, послідовних проектів, віконної котушки та потокового агрегатного плану досить багато накладних витрат:

Розділ плану

У SQL Server 2016 у вас є нова опція, яка полягає в тому, щоб включити пакетний режим обробки агрегатів вікон. Для цього потрібен якийсь індекс стовпців стовпців на столі, навіть якщо він порожній. Наявність індексу зберігання стовпців на даний момент необхідна для оптимізатора для розгляду планів пакетного режиму. Зокрема, це дає можливість набагато ефективнішого оператора пакетного режиму агрегації Window Aggregate.

Щоб перевірити це у вашому випадку, створіть порожній некластеризований індекс магазину стовпців:

 -- 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.