首页 > 解决方案 > 在 Microsoft SQL Server 中,是否可以以某种方式加速 Lag()?

问题描述

似乎(几乎)在聚集索引上扫描表,从“以前的记录”中总结一个字段,就像在整个表中总结该字段一样容易。但是没有:(有什么我能做的吗?

create table #Tmp(n int not null primary key)
insert into #Tmp values(0)

declare @k int = 1

while @k < 1024 * 1024 * 32
begin
    insert into #Tmp
    select n + @k
    from #Tmp

    select @k = @k + @k
end

declare @dummy bigint

declare @d1 datetime = GetDate()

select
    @dummy = Sum(Convert(bigint, n))
from
    #Tmp

declare @d2 datetime = GetDate()

select
    @dummy = Sum(convert(bigint, n0))
from
    (
    select
        n0 = Lag(n) over (order by n)
    from
        #Tmp
    ) as Q

declare @d3 datetime = GetDate()

select Convert(time(3), @d2 - @d1), Convert(time(3), @d3 - @d2)
-- 00:00:01.460, 00:00:46.273

drop table #Tmp

标签: sqlsql-serverperformancelagwindowed

解决方案


使用 2019 之前的 SQL Server,您可以通过创建具有列存储索引的虚拟表来利用批处理模式的一些好处。

在 SQL Server 2016 上运行窗口函数查询需要 25 秒:

在此处输入图像描述

但是,在创建下表之后

create table dbo.bmode (Id int not null)
create nonclustered columnstore index CC_BatchModeHack on dbo.bmode (Id) 

我可以使用外连接将它包含在查询中。它实际上根本不参与查询,但会诱使优化器为窗口函数选择批处理模式

select @dummy = Sum(Convert(bigint, n0))
from (
  select n0 = Lag(n) over (order by n)
  from #Tmp
  left join bmode on 1=0
)q

结果是执行时间下降到几乎 2 秒

在此处输入图像描述


推荐阅读