¿Cuál es el algoritmo interno de cómo funciona el operador Excepto bajo las cubiertas en SQL Server? ¿Toma internamente un hash de cada fila y compara?
David Lozinksi realizó un estudio, SQL: la forma más rápida de insertar nuevos registros donde todavía no existe . Mostró que la declaración Except es la más rápida para filas de números grandes; estrechamente vinculado a nuestros resultados a continuación.
Supuesto: creo que la unión izquierda sería la más rápida, ya que solo compara 1 columna, excepto que tomaría más tiempo, ya que tiene que comparar todas las columnas.
Con estos resultados, ahora nuestro pensamiento es ¿Excepto automáticamente e internamente toma un hash de cada fila? Miré el plan de ejecución Excepto y utiliza algo de hash.
Antecedentes: nuestro equipo estaba comparando dos tablas de montón. Tabla A Las filas que no están en la Tabla B, se insertaron en la Tabla B.
Las tablas de montón (del sistema de archivos de texto heredado) no tienen claves / guías / identificadores primarios. Algunas de las tablas tenían filas duplicadas, por lo que encontramos el hash de cada fila, eliminamos duplicados y creamos identificadores de clave principal.
1) Primero ejecutamos una declaración except, excluyendo (columna hash)
select * from TableA
Except
Select * from TableB,
2) Luego ejecutamos una combinación de combinación izquierda entre las dos tablas en el HashRowId
select *
FROM dbo.TableA A
left join dbo.TableB B
on A.RowHash = B.RowHash
where B.Hash is null
Sorprendentemente, el Except Statement Insert fue el más rápido.
Los resultados en realidad se corresponden con los resultados de las pruebas de David Lozinksi
Respuestas:
No diría que hay un algoritmo interno especial para
EXCEPT
. ParaA EXCEPT B
, el motor toma tuplas distintas (si es necesario) de A y resta filas que coinciden en B. No hay operadores de planes de consulta especiales. Lo distinto y la resta se implementan a través de los operadores típicos que vería con una ordenación o una unión. La unión de bucle anidado, la combinación de combinación y la combinación hash son compatibles. Para mostrar esto, arrojaré 15 millones de filas en un par de montones:El optimizador toma las decisiones habituales basadas en los costos sobre cómo implementar la ordenación y la unión. Con dos montones obtengo un hash join como se esperaba. Puede ver otros tipos de unión de forma natural agregando índices o cambiando los datos en cualquiera de las tablas. A continuación, forzo las combinaciones de fusión y bucle con sugerencias solo con fines ilustrativos:
No. Se implementa como cualquier otra combinación. Una diferencia es que los NULL se tratan como iguales. Este es un tipo especial de comparación que se puede ver en el plan de ejecución:
<Compare CompareOp="IS">
. Sin embargo, puede obtener el mismo plan con T-SQL que no incluye laEXCEPT
palabra clave. Por ejemplo, lo siguiente tiene exactamente el mismo plan deEXCEPT
consulta que la consulta que utiliza una combinación hash:Diferenciar el XML de los planes de ejecución solo revela diferencias superficiales en torno a los alias y cosas así. Los residuos de la sonda para las uniones hash hacen la comparación de filas. Son lo mismo para ambas consultas:
Si aún tiene dudas, ejecuté PerfView con la frecuencia de muestreo más alta disponible para obtener pilas de llamadas para la consulta con
EXCEPT
y la consulta sin ella. Aquí están los resultados uno al lado del otro:No hay diferencia real. Las pilas de llamadas allí están presentes hash de referencia debido a las coincidencias de hash en el plan. Si agrego índices para obtener una combinación de fusión natural, no verá ninguna referencia al hash en las pilas de llamadas:
Cualquier hash que ocurra se debe a la implementación de operadores de coincidencia hash. No hay nada especial sobre lo
EXCEPT
que conduce a una comparación de hashing interna especial.fuente