Jas*_*son 14 performance join sql-server window-functions sql-server-2016 query-performance
我有20M行的表,每一行有3列:time,id,和value。对于每个id和time,value状态都有一个。我想知道time特定id.
我使用了两种方法来实现这一点。一种方法是使用加入和另一种方法是使用功能导致的窗口/滞后与聚簇索引time和id。
我通过执行时间比较了这两种方法的性能。join方法需要16.3秒,窗口函数方法需要20秒,不包括创建索引的时间。这让我感到惊讶,因为窗口函数似乎是先进的,而连接方法是蛮力的。
下面是这两种方法的代码:
创建索引
create clustered index id_time
on tab1 (id,time)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
(仅通过订购可time节省 0.5 秒。)
这是Window函数方法的执行计划
IO统计
[![窗函数方法4的统计]](https://i.stack.imgur.com/IjuQW.png)
我检查了数据,sample_orig_month_1999似乎原始数据按id和排序得很好time。这是性能差异的原因吗?
看起来join方法比窗口函数方法有更多的逻辑读取,而前者的执行时间实际上更少。是不是因为前者的并行性更好?
我喜欢窗口函数方法,因为代码简洁,对于这个特定的问题,有什么方法可以加快速度吗?
我在 Windows 10 64 位上使用 SQL Server 2016。
Pau*_*ite 13
与自联接相比,LEAD和LAG窗口函数的行模式性能相对较低并不是什么新鲜事。例如,Michael Zilberstein 早在 2012 年就在 SQLblog.com 上写过它。(重复的)Segment、Sequence Project、Window Spool 和 Stream Aggregate 计划运算符有相当多的开销:
在 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;
Run Code Online (Sandbox Code Playgroud)
查询:
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;
Run Code Online (Sandbox Code Playgroud)
现在应该给出一个执行计划,如:
...这可能会执行得更快。
OPTION (MAXDOP 1)将结果存储在新表中时,您可能需要使用或其他提示来获得相同的计划形状。该计划的并行版本需要批处理模式排序(或可能是两个),这可能会慢一点。这更取决于您的硬件。
有关批处理模式窗口聚合运算符的更多信息,请参阅 Itzik Ben-Gan 的以下文章: