Recentemente terminei de ler o Plan Caching no SQL Server 2008 e fiquei confuso. Parece que, além de liberar totalmente o cache do plano ou exigir explicitamente a recompilação de um procedimento armazenado, as recompilações de procedimentos armazenados do SQL Server 2008 em diante são feitas no nível da instrução, e não no nível do procedimento armazenado.
Portanto, além de liberar explicitamente o cache ou exigir recompilações (por exemplo WITH RECOMPILE
), o que recompila um procedimento armazenado completo no SQL Server 2019 em vez de apenas recompilar instruções individuais?
Para dar um exemplo de onde estou confuso, considere o procedimento a seguir.
CREATE PROCEDURE FOO AS
BEGIN
SELECT * INTO #temp1 FROM table1
INSERT BAR1 SELECT * FROM #temp1
INSERT BAR2 SELECT * FROM #temp1
END
Posso pensar em muitas coisas que poderiam causar SELECT * INTO #temp1 FROM table1
a recompilação, mas seria estranho recompilar sem que as próximas linhas também recompilassem. Isso me faz pensar que deve haver algumas coisas no SQL Server que farão com que procedimentos armazenados inteiros sejam recompilados.
não muito
Fora o que foi listado na sua pergunta, não há realmente nenhuma causa genérica comum para um procedimento armazenado sempre recompilar um novo plano para cada instrução, pelo menos não para o do seu exemplo.
O SQL Server oferece algumas maneiras diferentes de rastrear recompilações, mas todas elas estão no nível de instrução. Provavelmente o mais fácil de obter respostas são os Eventos Estendidos. Não há nenhum evento para rastrear a recompilação no nível do objeto, que eu encontrei.
No SQL Server 2022, isso lista 23 motivos para recompilação, incluindo, uh, "Não é uma recompilação".
no entanto
Estou ciente de algumas coisas que impedem o cache do plano, o que faria parecer que um módulo precisa ser recompilado todas as vezes (embora, na realidade, seja mais como apenas compilar todas as vezes, eu acho).
Como Paulo observa em sua postagem:
Siga o link para alguns exemplos.
Ainda não tenho um post publicado sobre isso, mas a ideia geral é que quando há uma
IF
ramificação inexplorada em um procedimento armazenado que faz referência a um objeto que não existe, todo o lote não pode ser armazenado em cache.Sinta-se à vontade para acompanhar a demonstração abaixo. Observe que se você tentar obter um plano estimado para o procedimento armazenado conforme descrito abaixo, ou se executá-lo de uma forma que explore a ramificação com o objeto inexistente, ocorrerá um erro.
Claro, você pode definir explicitamente o procedimento armazenado para recompilar toda vez que for executado, com a opção recompile assim:
Opções alternativas também executam o procedimento armazenado com a dica de recompilação:
Ou chamando explicitamente o procedimento do sistema
sp_recompile
: