Usar IF no T-SQL enfraquece ou interrompe o cache do plano de execução?

20

Foi-me sugerido que o uso de instruções IF em lotes t-SQL é prejudicial ao desempenho. Estou tentando encontrar alguma confirmação ou validar esta afirmação. Estou usando o SQL Server 2005 e 2008.

A afirmação é que, com o seguinte lote:

IF @parameter = 0
 BEGIN
  SELECT ... something
 END

ELSE
 BEGIN
  SELECT ... something else
 END

O SQL Server não pode reutilizar o plano de execução gerado porque a próxima execução pode precisar de uma ramificação diferente. Isso implica que o SQL Server eliminará totalmente uma ramificação do plano de execução, pois, para a execução atual, ele já pode determinar qual ramificação é necessária. Isso é mesmo verdade?

Além disso, o que acontece neste caso: -

IF EXISTS (SELECT ....)
 BEGIN
  SELECT ... something
 END

ELSE
 BEGIN
  SELECT ... something else
 END

onde não é possível determinar antecipadamente qual ramificação será executada?

AnthonyWJones
fonte
11
O SQL Server pode e reutiliza o plano de execução, pois não considera as ramificações, apenas as instruções contidas nas ramificações.
Martinc

Respostas:

10

O SQL Server otimiza o processo de compilação do plano de consulta para o procedimento armazenado ignorando as ramificações condicionais dentro do procedimento armazenado. O plano será gerado com base nos parâmetros usados ​​para a primeira execução, isso causará problemas se os parâmetros forem diferentes para as ramificações.

Eu colocaria o SQL para cada uma das ramificações em seu próprio procedimento armazenado, para que o plano gerado se baseie no uso real dos parâmetros para essa ramificação.

MartinC
fonte
6

O único atalho será IF 1 = 1

@Parameter e EXISTS ainda requerem processamento para o "caso geral" ( @parameter = 42digamos)

Dizendo isso ... o que o plano de execução real diz, bem como o criador de perfil capturando eventos de recomposição? (Eu não gosto de planos estimados de acordo com a resposta de Jao)

gbn
fonte
3

Tente exibir o plano de execução estimado, não o real. Você verá que o primeiro contém o CONDoperador.

Esse operador também foi incluído no plano de execução em cache. No seu exemplo, o plano de extração estimado conterá um operador COND e 2 filiais SELECT e, portanto, será totalmente reutilizável. Porque, ao executar um lote, o SQL Server avalia não apenas instruções DML, mas também todas as outras, obtendo-as do plano.

O plano de execução interna é uma estrutura semelhante à árvore de expressões.

Tom V - Equipe Monica
fonte
0

Os planos serão criados com base nos parâmetros passados, portanto, na realidade, eu diria Não - ter uma lógica condicional que normalmente é baseada em parâmetros não prejudica o desempenho.

Você obterá vários planos produzidos, assumindo que os parâmetros causem uma variação suficiente para o otimizador de consultas perceber.

Você pode ver qual, ativando o plano Show Execution, executando os scripts - observe as diferenças no plano. Ao executar os procedimentos (estou assumindo procedimentos armazenados aqui), você notará que a primeira vez é geralmente mais rápida, a segunda ocorrência usa o plano armazenado. Altere os parâmetros e repita e execute os parâmetros originais - em teoria, o plano ainda estará no cache, mas depende do uso do servidor (marcações de cache - eles não ficam para sempre ...) etc.

Barry King
fonte
0

Talvez tenha sido aprimorado em 2005 e 2008, mas o uso de condicionais em 2000 provavelmente seria pior do que o descrito, ele compilaria um plano para lidar melhor com a primeira execução do procedimento e, em seguida, usaria esse plano para executar o procedimento mesmo quando as condições mudou. Na minha experiência, isso causou consultas que eram executadas em minutos para serem executadas em horas. Embora eu use 2008 agora e usei 2005, não posso comentar sobre como os códigos funcionam lá, pois não os uso mais.


fonte
2
2005 + tem recompilação nível de instrução para que você não tem "um plano por sp" o tempo todo mais
GBN