declare @codigo int
declare @valor float
declare ccursor cursor for
select codigo, valor from tab1
open ccursor
fetch next from ccursor into @codigo,@valor
WHILE @@FETCH_STATUS = 0
BEGIN
if exists (select 1 from tab2 where codigo = @codigo)
update tab2 set valortab2 = valortab1 + @valor where codigo = @codigo
else
insert into tab2(codigo, valortab1,valortab2) values (@codigo,@valor,0)
fetch next from ccursor into @codigo,@valor
end
close ccursor
deallocate ccursor
Ou seja, para cada linha de tab1 procurava-se em TAB2. Se existisse atualizava o valor, se não inseria uma nova linha.
Este processo assim, para 980 mil linhas na TAB1, demorava 47 minutos.
Bom, este é o tipico pensamento llinha a linha, que a maiora de desenvolvedore seniors da era micro (inclusive eu) tem , epoca que os recursos eram limitados neste aspecto.
Poxa eu fui programador clipper muitos anos, era seek e do while.
Mas e se a gente mudasse o pensamento ?
E se a gente atualizasse o que existe e inserisse o que não existe ?…
Vamos mais a fundo e se a gente atualizasse o que existe, guardasse o codigo destas linhas atualizadas numa tabela e inserisse na tab2 as que nao existem no join da tab1 com esta nova tabela.
Vamos lá
declare @tabela table (codigo int)
update a
set a.valortab2 = a.valortab1 + b.valor
OUTPUT inserted.codigo INTO @tabela
from tab2 a, tab1 b
where a.codigo = b.codigo
insert into tab2( codigo, valortab1, valortab2)
select a.codigo, a.valor, 0 from tab1 a
where not exists ( select 1 from @tabela b where a.codigo = b.codigo)
Esta alteração de pensamento, passou para 7 segundos, de 5 a 7 em média.
Usando a clausula output (pois era 2005..se fosse 2008 eu usaria o merge) eu coloquei na @tabelas as linhas que foram atualizadas e depois inseri as que nao tivessem no join dela com a tab1
O que eu fiz ?..nada de milagres ou tecnicas extraordinárias de tuning…simplesmente pensei SET BASED…conjunto de linhas e nao linha a linha.
Grande abraço a todos
Laerte Junior