Fuente autorizada que <> y! = Son idénticas en rendimiento en SQL Server

74

Considere esta respuesta en SO que tranquiliza al que pregunta sobre el <>operador que:

<>es ... lo mismo que !=.

Pero luego un comentarista aparece y dice:

Es cierto que son, funcionalmente, lo mismo. Sin embargo, cómo los usa el optimizador de SQL es muy diferente. = /! = simplemente se evalúan como verdadero / falso, mientras que <> significa que el motor tiene que mirar y ver si el valor es mayor o menor que, lo que significa más sobrecarga de rendimiento. Es algo a tener en cuenta al escribir consultas que pueden ser costosas.

Estoy seguro de que esto es falso, pero para abordar posibles escépticos, me pregunto si alguien puede proporcionar una fuente autorizada o canónica para demostrar que estos operadores no son funcionalmente iguales, sino idénticos en todos los aspectos.

ErikE
fuente

Respuestas:

144

Durante el análisis , SQL Server llama sqllang!DecodeCompOppara determinar el tipo de operador de comparación presente:

Pila de llamadas

Esto ocurre mucho antes de que algo en el optimizador se involucre.

De operadores de comparación (Transact-SQL)

Operadores de comparación y significados

Al rastrear el código utilizando un depurador y símbolos públicos *, se sqllang!DecodeCompOpdevuelve un valor en el registro eax** de la siguiente manera:

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

!=y <>ambos devuelven 5, por lo que no se pueden distinguir en todas las operaciones posteriores (incluida la compilación y la optimización).


Aunque es secundario al punto anterior, también es posible (por ejemplo, usar el indicador de traza no documentado 8605) mirar el árbol lógico pasado al optimizador para confirmar que ambos !=y <>mapear ScaOp_Comp x_cmpNe(comparación de operador no escalar igual).

Por ejemplo:

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

LogOp_Project QCOL: [P] .ProductID
    LogOp_Select
        LogOp_Get TBL: Production.Product (alias TBL: P)
        ScaOp_Comp x_cmpNe
            ScaOp_Identifier QCOL: [P] .ProductID
            ScaOp_Const TI (int, ML = 4) XVAR (int, no propiedad, valor = 4)
    AncOp_PrjList 

Notas al pie

* Yo uso WinDbg ; Otros depuradores están disponibles. Los símbolos públicos están disponibles a través del servidor de símbolos habitual de Microsoft. Para obtener más información, consulte Profundizar en SQL Server utilizando Minidumps del Equipo de asesoramiento al cliente de SQL Server y Depuración de SQL Server con WinDbg: una introducción de Klaus Aschenbrenner.

** El uso de EAX en derivados Intel de 32 bits para valores de retorno de una función es común. Ciertamente, el Win32 ABI lo hace de esa manera, y estoy bastante seguro de que hereda esa práctica de los viejos tiempos de MS-DOS, donde AX se usaba para el mismo propósito: Michael Kjörling

Paul White
fuente
58

Trabajo en Microsoft en soporte de SQL y le pregunté a Jack Li, ingeniero de escalamiento y experto en materia del rendimiento del servidor SQL, "¿trata SQL! = ¿Es diferente de <>?" y él dijo: "Son lo mismo".

Stacylaray
fuente
8

Creo que lo siguiente prueba que <>no hace 2 comparaciones.

  1. SQL Standard 92 define <>como operador no igual ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Técnicamente, !=es una extensión del estándar (aunque no puedo pensar en ningún RDBMS que no lo implemente).
  2. Si SQLServer se tratara <>como 2 operadores, no como uno, haría lo mismo, lo ><que en realidad es un error de sintaxis.
a1ex07
fuente
1

Eso es incorrecto, Books Online (BOL) dice que son funcionalmente iguales:

! = (No es igual a) (Transact-SQL)

Y si observa un plan de ejecución donde !=se usa, en Predicate, cambia != a <>.

Ryan Cooper
fuente
2
El problema es que el lenguaje "funcionalmente igual" ya está admitido en el comentario referenciado, pero hace una distinción adicional sobre el rendimiento, a pesar de que usted y yo sabemos que "funcionalmente igual" incluye cómo funciona realmente y cualquier característica de rendimiento del mismo. Si uno fuera a probar esto más allá de todo escepticismo determinado, ¿qué haría uno?
ErikE