Suspeitos comuns:
- constantes em adhoc, parâmetros no código
- incompatibilidade de tipos de dados no código
- cheirar parâmetro
Ponto 1: o otimizador pode escolher o melhor plano para as constantes.
Mude as constantes = mude o plano. Uma plenária parametrizada é recuperável
O ponto 2 introduzirá conversões implícitas devido à precedência do tipo de dados,
por exemplo, coluna varchar em comparação com o parâmetro nvarchar
Ponto 3: use mascaramento de parâmetro ou OPTIMIZE FOR UNKNOWN
Edit: Para testar: execute proc armazenado, execute sp_updatestats, execute novamente. Isso invalidará os planos em cache, o que é melhor do que limpar o cache do plano
Edit: após o comentário de jcolebrand
Você pode desativar o sniffing de várias maneiras. Os 3 principais são
- RECOMPLEM. Isso é IMO bobo.
- OTIMIZAR (SIC) PARA DESCONHECIDO
- Máscara de parâmetro
Máscara de parâmetro:
DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam
SELECT...WHERE column = @MaskedParam
O mascaramento e a dica OPTIMIZE têm o mesmo efeito (talvez por razões diferentes). Ou seja, o otimizador precisa usar estatísticas e distribuição de dados ( Nota: ainda em teste por Mark Storey-Smith ) avaliar os parâmetros por seus próprios méritos ? , e não como eles foram a última chamada. O otimizador pode recompilar ou não. O SQL Server 2005 adicionou a recompilação no nível da instrução para que houvesse menos impacto
Agora, por que um plano com parâmetros "sniffed" é "pegajoso" comparado a parâmetros mascarados / "desconhecidos", não tenho certeza.
Eu uso o mascaramento de parâmetros desde o SQL Server 2000 para todos, exceto o código mais simples. Observei que é provável que isso aconteça com código mais complexo. E no meu antigo emprego, tenho alguns procedimentos de relatório que podem alterar os padrões dos parâmetros do plano. Eu acho que a abordagem do "culto à carga" foi mais fácil do que uma ligação de suporte.
Edit 2, 12 Out 2011, depois de algum bate-papo
O mascaramento de parâmetro e OPTIMIZE FOR UNKNOWN têm o mesmo efeito, pelo que sei.
A dica é mais limpa do que o mascaramento, mas foi adicionada ao SQL Server 2008.
A detecção de parâmetros ocorre no momento da compilação.
WITH RECOMPILE gera um novo plano a cada execução. Isso significa que uma má escolha de padrões influenciará o plano. No meu último trabalho, pude demonstrar isso facilmente com algum código de relatório: a alteração dos padrões dos parâmetros alterou o plano, independentemente dos parâmetros fornecidos.
Este artigo do MS Connect é interessante: Uso de índice abaixo do ideal no procedimento armazenado (mencionado em uma das respostas de SO abaixo)
- Bob Beauchemin também menciona
Questões pendentes
O sniffing ainda se aplica a WITH RECOMPILE? Ou seja, se o otimizador souber descartar o plano, ele pretende reutilizá-lo?
Por que os planos sniffed são "pegajosos"?
Links de SO:
WHERE
cláusula?