Eu tenho uma tabela com linhas 20m, e cada linha tem 3 colunas: time
, id
, e value
. Para cada id
e time
, existe um value
para o status. Quero saber os valores de lead e lag de um determinado time
para um específico id
.
Eu usei dois métodos para conseguir isso. Um método está usando junção e outro método está usando as funções da janela lead / lag com o índice clusterizado em time
e id
.
Eu comparei o desempenho desses dois métodos pelo tempo de execução. O método de junção leva 16,3 segundos e o método da função de janela leva 20 segundos, não incluindo o tempo para criar o índice. Isso me surpreendeu porque a função window parece ser avançada enquanto os métodos de junção são força bruta.
Aqui está o código para os dois métodos:
Criar índice
create clustered index id_time
on tab1 (id,time)
Método de junção
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
Estatísticas de E / S geradas usando SET STATISTICS TIME, IO ON
:
Aqui está o plano de execução para o método de junção
Método da função de janela
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
(Solicitar apenas time
economiza 0,5 segundos.)
Aqui está o plano de execução para o método da função Window
Estatísticas de IO
[
Eu verifiquei os dados sample_orig_month_1999
e parece que os dados brutos estão bem ordenados por id
e time
. É este o motivo da diferença de desempenho?
Parece que o método de junção tem leituras mais lógicas que o método da função de janela, enquanto o tempo de execução do primeiro é realmente menor. É porque o primeiro tem um paralelismo melhor?
Eu gosto do método de função de janela por causa do código conciso, existe alguma maneira de acelerá-lo para esse problema específico?
Estou usando o SQL Server 2016 no Windows 10 de 64 bits.