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:
- 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. - 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.