Consulta Otimização TSQL e de outra forma
-
23-08-2019 - |
Pergunta
Suponha que eu tenho uma instrução SQL como o seguinte com a variável de set @FOO algum lugar mais cedo no código:
SELECT FIELDLIST
FROM TABLE
WHERE
(FIELD = @FOO OR @FOO IS NULL)
É o otimizador de consulta inteligente o suficiente para fazer o segundo lado da primeira OR (@FOO IS NULL) porque (outra hipótese) é mais rápido para fazer uma verificação nula do que está a fazer uma comparação de campo?
Já fiz alguns de benchmarking informal e não só eu não vejo uma diferença, eu recebo diferentes momentos resultado em minhas tentativas que joga fora a capacidade de fazer uma comparação adequada.
Solução
A resposta curta ...
Sim , o otimizador é inteligente o suficiente.
A resposta mais longa ...
SQL é declarativa ao invés de imperativo:. Sua consulta é uma descrição dos critérios que os resultados devem atender, é não instruções passo-a-passo sobre como gerar esses resultados
O otimizador executa a consulta na ordem mais eficiente. Ele não garante a avaliar suas cláusulas em qualquer ordem particular, ou mesmo avaliá-los em tudo -? Se pode obter os resultados corretos sem avaliar uma cláusula particular, então por que se incomoda
A ordem de avaliação real de qualquer consulta particular é um detalhe de implementação e pode mudar ao longo do tempo (por exemplo, como as estatísticas sobre a mudança tabela).
Na prática, o otimizador irá ocasionalmente fazer as coisas erradas, mas neste caso particular - comparar uma variável para NULL contra a leitura de uma tabela ou índice - Eu não acho que há muita chance de que estragar, embora você pode querer considerar o uso OPTION(RECOMPILE)
ou OPTION(OPTIMIZE FOR ...)
.
Outras dicas
Tente testá-lo com as cláusulas na ordem oposta:
SELECT FIELDLIST
FROM TABLE
WHERE
(@FOO IS NULL OR FIELD = @FOO)
Você pode achar que o primeiro teste será curto-circuito na segunda, mas não vice-versa.
Na minha experiência, às vezes é ainda mais rápido de usar duas consultas e um "UNIÃO" em vez de um "OU" cláusula.
SELECT FIELDLIST
FROM TABLE
WHERE
(FIELD = @FOO)
UNION
SELECT FIELDLIST
FROM TABLE
WHERE
(@FOO IS NULL)
Esta abordagem tem a desvantagem de duplicar a instrução SELECT, mas o aumento de desempenho 1,500% foi que o justificam. Claro, isso depende da estrutura de banco de dados (no meu caso era muito ruim, e eu não poderia mudá-lo).
É o suficiente inteligente para aplicar a condição mais rápido em primeiro lugar, supondo que ele pode julgar que a comparação será mais rápido no caso geral. Neste caso, a verificação de NULL será quase sempre mais rápido porque tem que comparar no máximo, um byte de cada lado da expressão e pode levar-lo.
Um fator que pode estar em jogo aqui se esta consulta está dentro de um sproc é "parâmetro sniffing". Isso pode levar a tempos de resposta de consulta inconsistentes. Para corrigir esse declarar uma variável interna em seu sproc e atribuir esta variável para o valor do parâmetro e, em seguida, usar a variável interna em sua cláusula where ou usar o RECOMPILAR cláusula no seu sproc. Há muitas ligações sobre este assunto.