Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Quais são as principais diferenças entre OPTION(OPTIMIZE FOR UNKNOWN) e OPTION(RECOMPILE)?


Sim vai.

Existem duas diferenças principais entre OPTION(OPTIMIZE FOR UNKNOWN) e OPTION(RECOMPILE) como pode ser visto nesta citação de MSDN :



Assim, as duas principais diferenças são:
  1. Caching (ou não) do plano de consulta.

Normalmente, o plano de consulta gerado é armazenado em cache e reutilizado. OPTIMIZE FOR UNKNOWN não afeta esta característica do motor. RECOMPILE suprime esse recurso e informa ao mecanismo para descartar o plano e não colocá-lo no cache.
  1. Usar (ou não) valores de parâmetros reais durante a geração do plano.

Normalmente o otimizador "fareia" os valores dos parâmetros e usa esses valores ao gerar o plano. OPTIMIZE FOR UNKNOWN suprime esse recurso e informa ao mecanismo para tratar todos os parâmetros como se seus valores fossem desconhecidos. O Optimizer possui regras e heurísticas integradas sobre como usar as estatísticas disponíveis para vários critérios de filtragem. Consulte Otimizar para… medíocre? para mais detalhes. Normalmente, a detecção de parâmetros é usada na primeira execução da consulta/procedimento armazenado e usa os valores dos parâmetros durante a primeira execução. O plano gerado é armazenado em cache e posteriormente pode ser reutilizado.

Uma coisa não óbvia para lembrar aqui é que em ambos os casos (normal sem nenhuma dica de consulta e com OPTIMIZE FOR UNKNOWN dica) o plano gerado deve ser válido e produzir resultado correto para qualquer valor de parâmetro possível. Ele é adaptado aos valores sniffados que foram usados ​​durante a primeira execução no caso normal/sem dica; ele não é adaptado a nenhum valor específico no OPTIMIZE FOR UNKNOWN caso, mas ainda é válido se o parâmetro for alterado posteriormente de alguma forma.

Isso é significativo e impede que o otimizador realize certas transformações e simplificações do plano.

OPTION(RECOMPILE) permite que o otimizador inline os valores reais dos parâmetros durante cada execução e o otimizador usa os valores reais dos parâmetros para gerar um plano melhor. Ele não precisa se preocupar que o plano gerado pode não funcionar com algum outro valor de parâmetro, porque o plano não será armazenado em cache e reutilizado.

Este efeito é visível principalmente para as Condições de pesquisa dinâmica consultas. Por exemplo:
SELECT ...
FROM T
WHERE
    (@ParamSomeID = 0)
    OR
    (
        @ParamSomeID = -1
        AND
        T.SomeID NOT IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
        )
    )
    OR
    (
        T.SomeID IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
            WHERE OtherTable.SomeID = @ParamSomeID
        )
    )
OPTION(RECOMPILE)

Se @ParamSomeID é 0 otimizador trataria a consulta como se não tivesse nenhum WHERE cláusula em tudo. O plano não mencionaria OtherTable de forma alguma.

Se @ParamSomeID é -1 , o plano se juntaria a T para OtherTable usando Left Anti Semi Join e faria a varredura de toda a OtherTable .

Se @ParamSomeID é, digamos, 5, o plano faria uma busca de índice no índice exclusivo em OtherTable e leia apenas uma linha de OtherTable .

Sem OPTION(RECOMPILE) esse tipo de simplificação e transformação não aconteceria.

Outro motivo para usar OPTION(RECOMPILE) é quando sua distribuição de dados é muito distorcida. Por exemplo, você tem uma tabela com 1 milhão de linhas. Uma coluna tem valor 0 em 990 mil linhas e valores de 1 a 10 em 1 mil linhas. As consultas que filtram nesta coluna devem ter planos diferentes dependendo do valor real do filtro.

Nos dois exemplos acima OPTIMIZE FOR UNKNOWN geraria um plano medíocre.