Diferença monumental no tempo de execução entre as consultas ao usar a dica de consulta RECOMPILE

16

Eu tenho duas consultas quase idênticas em execução na mesma instância do SQL Server 2005:

  1. A primeira é a SELECTconsulta original gerada pelo LINQ (eu sei, eu sei ... eu não sou o desenvolvedor de aplicativos, apenas o DBA :).
  2. O segundo é exatamente o mesmo que o primeiro, adicionado a OPTION (RECOMPILE)no final.

Nada mais foi alterado.

O primeiro leva 55 segundos toda vez que é executado.
O segundo leva 2 segundos.

Ambos os conjuntos de resultados são idênticos.

Por que essa dica geraria um ganho tão dramático no desempenho?

A entrada do Books Online RECOMPILEnão oferece uma explicação muito detalhada:

Instrui o Mecanismo de Banco de Dados do SQL Server a descartar o plano gerado para a consulta após a execução, forçando o otimizador de consulta a recompilar um plano de consulta na próxima vez que a mesma consulta for executada. Sem especificar RECOMPILE, o Mecanismo de Banco de Dados armazena em cache os planos de consulta e os reutiliza. Ao compilar planos de consulta, a dica de consulta RECOMPILE usa os valores atuais de quaisquer variáveis ​​locais na consulta e, se a consulta estiver dentro de um procedimento armazenado, os valores atuais serão transmitidos para qualquer parâmetro.

RECOMPILE é uma alternativa útil para criar um procedimento armazenado que usa a cláusula WITH RECOMPILE quando apenas um subconjunto de consultas dentro do procedimento armazenado, em vez de todo o procedimento armazenado, deve ser recompilado. Para obter mais informações, consulte Recompilando procedimentos armazenados. RECOMPILE também é útil quando você cria guias de plano. Para obter mais informações, consulte Otimizando consultas em aplicativos implantados usando guias de plano.

Como minha consulta possui muitas variáveis ​​locais, meu palpite é que o SQL Server pode (seriamente) otimizá-la quando uso a OPTION (RECOMPILE)dica de consulta.

Em todo lugar que olho, as pessoas estão dizendo que isso OPTION (RECOMPILE)deve ser evitado. A explicação para isso é geralmente que o uso dessa dica do SQL Server não pode reutilizar esse plano de exceção e, portanto, precisa perder tempo recompilando-o sempre.
(Mas) Dada a gigantesca vantagem de desempenho, estou inclinado a pensar que usar essa dica de consulta desta vez seria uma coisa boa.

Devo usá-lo? Caso contrário, existe uma maneira de forçar o SQL Server a usar um plano de execução melhor sem essa dica e sem alterar o aplicativo?

ivanmp
fonte

Respostas:

16

Conforme documentado no artigo Estatísticas usadas pelo Query Optimizer no Microsoft SQL Server 2005

Se você usar uma variável local em um predicado de consulta em vez de um parâmetro ou literal, o otimizador recorrerá a uma estimativa de qualidade reduzida ou uma estimativa da seletividade do predicado. Use parâmetros ou literais na consulta em vez de variáveis ​​locais

Quando o otimizador não possui estatísticas utilizáveis ​​para uma coluna, ele supõe que um =predicado corresponderá a 10% das linhas, BETWEEN9% e qualquer um >, >=, < and <=deles corresponderá a 30%. Se houver estatísticas de coluna disponíveis, um =predicado será tratado de maneira diferente, conforme abaixo.

Mesmo quando variáveis ​​locais são usadas em uma consulta, uma estimativa melhor que uma suposição é usada no caso de predicados de igualdade. A seletividade para condições do formulário " @local_variable = column_name" é estimada usando a frequência do valor médio do histograma para column_name. Portanto, por exemplo, se a coluna nome_da_coluna contiver todos os valores exclusivos, 1/(number of unique values in column)será usada uma estimativa de seletividade , que é precisa.

Portanto, isso é essencialmente o mesmo que usar para OPTIMIZE FOR (UNKNOWN). Pode ser mais preciso do que um 10%palpite simples, mas não é adaptado aos valores específicos que você está consultando.

Para forçar o SQL Server a otimizar uma consulta toda vez que ela é executada e usar os valores de variáveis ​​locais para estimar cardinalidade e custo durante a otimização da consulta, adicione a RECOMPILEdica de consulta à consulta.

RECOMPILEPresumivelmente, com o uso de você, você obtém estimativas de cardinalidade mais precisas e, portanto, um plano diferente com pedidos de junção / tipos de junção mais adequados ao número de linhas retornadas de diferentes partes da sua consulta real.

Martin Smith
fonte