У мене є таблиця з 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
Статистика ІО
[
Я перевірив дані в, sample_orig_month_1999
і здається, що необроблені дані добре впорядковані id
і time
. Це причина різниці у виконанні?
Здається, що метод з'єднання має більше логічних зчитувань, ніж метод віконної функції, тоді як часу виконання для першого фактично менше. Це тому, що перший має кращий паралелізм?
Мені подобається метод функції вікна через стислий код, чи є спосіб його прискорити для цієї конкретної проблеми?
Я використовую SQL Server 2016 у Windows 10 64 біт.