我有20M行的表,每一行有3列:time
,id
,和value
。对于每个id
和time
,value
状态为。我想知道的超前滞后一定的值,time
为特定的id
。
我使用了两种方法来实现此目的。一种方法是使用连接,另一种方法是使用窗口函数超前/滞后以及在time
和上的聚集索引id
。
我按执行时间比较了这两种方法的性能。join方法需要16.3秒,而window函数方法需要20秒,这不包括创建索引的时间。这使我感到惊讶,因为在join方法是蛮力的情况下,窗口功能似乎已被改进。
这是这两种方法的代码:
创建索引
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
以下命令生成的IO统计信息:
这是join方法的执行计划
窗函数法
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秒。)
这是Window函数方法的执行计划
IO统计
[
我检查了数据,sample_orig_month_1999
似乎原始数据按id
和排序良好time
。这是性能差异的原因吗?
似乎join方法比window函数方法具有更多的逻辑读取,而前者的执行时间实际上更少。是因为前者具有更好的并行性吗?
由于代码简洁,我喜欢window函数方法,有什么方法可以解决这个特定问题?
我正在Windows 10 64位上使用SQL Server 2016。