У меня есть таблица с 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]](https://i.stack.imgur.com/IjuQW.png)
Я проверил данные, sample_orig_month_1999и кажется, что исходные данные хорошо упорядочены по idи time. Это причина разницы в производительности?
Кажется, что метод соединения имеет больше логических чтений, чем метод оконной функции, в то время как время выполнения для первого фактически меньше. Это потому, что у первого лучше параллелизм?
Мне нравится метод оконной функции из-за лаконичного кода, есть ли способ ускорить его для этой конкретной проблемы?
Я использую SQL Server 2016 в Windows 10 64 бит.


