Origem autorizada que <> e! = São idênticas no desempenho no SQL Server

74

Considere esta resposta no SO que tranquiliza o solicitante sobre o <>operador que:

<>é ... o mesmo que !=.

Mas então um comentarista aparece e diz:

É verdade que eles são, funcionalmente, iguais. No entanto, como o otimizador de SQL os utiliza é muito diferente. = /! = são simplesmente avaliados como verdadeiro / falso, enquanto <> significa que o mecanismo precisa observar e ver se o valor é maior ou menor que, o que significa mais sobrecarga de desempenho. Apenas algo a considerar ao escrever consultas que podem ser caras.

Estou confiante de que isso é falso, mas, a fim de abordar potenciais céticos, pergunto-me se alguém pode fornecer uma fonte autorizada ou canônica para provar que esses operadores não são apenas funcionalmente iguais, mas idênticos em todos os aspectos?

ErikE
fonte

Respostas:

144

Durante a análise , o SQL Server chama sqllang!DecodeCompOppara determinar o tipo de operador de comparação presente:

Pilha de chamadas

Isso ocorre muito antes de qualquer coisa no otimizador se envolver.

De operadores de comparação (Transact-SQL)

Operadores e significados de comparação

Rastrear o código usando um depurador e símbolos públicos *, sqllang!DecodeCompOpretorna um valor no registro eax** da seguinte maneira:

╔════╦══════╗
║ Op ║ Code ║
╠════╬══════╣
║ <  ║    1 ║
║ =  ║    2 ║
║ <= ║    3 ║
║ !> ║    3 ║
║ >  ║    4 ║
║ <> ║    5 ║
║ != ║    5 ║
║ >= ║    6 ║
║ !< ║    6 ║
╚════╩══════╝

!=e <>ambos retornam 5, portanto são indistinguíveis em todas as operações posteriores (incluindo compilação e otimização).


Embora seja secundário ao ponto acima, também é possível (por exemplo, usando o sinalizador de rastreio não documentado 8605) observar a árvore lógica transmitida ao otimizador para confirmar que ambos !=e o <>mapeamento ScaOp_Comp x_cmpNe(comparação do operador escalar não é igual).

Por exemplo:

SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID != 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);

SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID <> 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);

ambos produzem:

QCOL do LogOp_Project: [P] .ProductID
    LogOp_Select
        LogOp_Get TBL: Production.Product (também conhecido por TBL: P)
        ScaOp_Comp x_cmpNe
            ScaOp_Identifier QCOL: [P] .ProductID
            ScaOp_Const TI (int, ML = 4) XVAR (int, Não possuído, Valor = 4)
    AncOp_PrjList 

Notas de rodapé

* Eu uso o WinDbg ; outros depuradores estão disponíveis. Símbolos públicos estão disponíveis no servidor de símbolos da Microsoft. Para obter mais informações, consulte Analisando mais detalhadamente o SQL Server usando Minidumps pela equipe de consultoria ao cliente do SQL Server e a depuração do SQL Server com WinDbg - uma introdução por Klaus Aschenbrenner.

** O uso do EAX em derivados da Intel de 32 bits para valores de retorno de uma função é comum. Certamente, a ABI do Win32 faz dessa maneira, e tenho certeza de que herda essa prática dos velhos tempos do MS-DOS, onde o AX era usado para o mesmo objetivo - Michael Kjörling

Paul White
fonte
58

Trabalho na Microsoft no suporte a SQL e perguntei a Jack Li, engenheiro sênior de escalonamento e especialista no assunto do desempenho do SQL Server: "O SQL trata! = Diferente de <>?" e ele disse: "Eles são os mesmos".

stacylaray
fonte
8

Eu acho que o seguinte prova que <>não faz 2 comparações.

  1. O SQL Standard 92 define <>como operador não igual a ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Tecnicamente, !=é uma extensão do padrão (mesmo que eu não consiga pensar em nenhum RDBMS que não o implemente).
  2. Se o SQLServer tratasse <>como 2 operadores, não um, ele faria o mesmo pelo ><qual, na verdade, é um erro de sintaxe.
a1ex07
fonte
1

Isso está incorreto, o Books Online (BOL) diz que eles são funcionalmente iguais:

! = (Não é igual a) (Transact-SQL)

E se você olhar para um plano de execução em que !=é usado, em Predicate, ele muda != para <>.

Ryan Cooper
fonte
2
O problema é que o idioma "funcionalmente igual" já é admitido no comentário mencionado, mas faz uma distinção adicional sobre desempenho, apesar de você e meu conhecimento de que "funcionalmente igual" inclui como realmente funciona e quaisquer características de desempenho. Se alguém iria provar isso além de todo ceticismo determinado, o que faria?
ErikE