Eu tenho a consulta abaixo:
select databasename
from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)
A consulta acima é concluída em três segundos.
Se a consulta acima retornar algum valor, queremos que o procedimento armazenado saia, então eu o reescrevi como abaixo:
If Exists(
select databasename
from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)
)
Begin
Raiserror('Source missing',16,1)
Return
End
No entanto, isso leva 10 minutos.
Posso reescrever a consulta acima, como abaixo, que também é concluída em menos de 3 segundos:
select databasename
from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source
if @@rowcount >0
Begin
Raiserror('Source missing',16,1)
Return
End
O problema com a reescrita acima é que a consulta acima faz parte de um procedimento armazenado maior e retorna vários conjuntos de resultados. Em C #, iteramos em cada conjunto de resultados e fazemos algum processamento.
O exemplo acima retorna um conjunto de resultados vazio; portanto, se eu seguir essa abordagem, tenho que alterar meu C # e fazer a implantação novamente.
Então, minha pergunta é:
por que usar apenas
IF EXISTS
altera o plano para levar tanto tempo?
Abaixo estão os detalhes que podem ajudá-lo e deixe-me saber se você precisar de mais detalhes:
- Crie tabela e script estatístico para obter o mesmo plano que o meu
- Plano de execução lenta
Plano de execução rápida
Plano lento usando Brentozar Cole o plano
Plano rápido usando Brentozar Cole o plano
Nota: Ambas as consultas são as mesmas (usando parâmetros), a única diferença é EXISTS
(eu posso ter cometido alguns erros ao anonimizar).
Os scripts de criação de tabela estão abaixo:
http://pastebin.com/CgSHeqXc - estatísticas da tabela pequena
http://pastebin.com/GUu9KfpS - estatísticas da tabela grande