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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top