¿Cuál es la forma más eficiente de comparar dos grandes conjuntos de resultados en SQL Server 2012?

9

El consejo actual para la forma más eficiente de comparar dos conjuntos grandes de resultados / filas parece ser utilizar el EXCEPToperador. Este script SQL autónomo a continuación se vuelve muy ineficiente a medida que aumenta el tamaño de las filas (cambie los valores de @last). He intentado encontrar entradas únicas en una tabla combinada pero sin ninguna mejora.

DECLARE @first AS INT, @step AS INT, @last AS INT; 

-- This script is comparing two record sets using EXCEPT
-- I want to find additions from OLD to NEW
-- As number of rows increase performance gets terrible
-- I don't have to use two tables. I could use one combined table but I want the same result as quickly as possible

-- Compare 100 to 110 rows - 0 seconds
-- Compare 1000 to 1010 rows - 1 seconds
-- Compare 10000 to 10010 rows - 16 seconds
-- Compare 100000 to 100010 rows - ABORT after 8 minutes (tables are populated in 18 seconds)

DECLARE @temptableOLD TABLE ([Result1] int);
SET @step = 1;  SET @first = 1; SET @last = 100000
WHILE(@first <= @last) BEGIN INSERT INTO @temptableOLD VALUES(@first) SET @first += @step END

DECLARE @temptableNEW TABLE ([Result1] int);
SET @step = 1;  SET @first = 1; SET @last = 100010
WHILE(@first <= @last) BEGIN INSERT INTO @temptableNEW VALUES(@first) SET @first += @step END

select * from @temptableNEW
except
select * from @temptableOLD
Will Healey
fuente

Respuestas:

8

EXCEPTimplica una DISTINCToperación.

Lo usaría NOT EXISTSsi esto no fuera realmente necesario.

Sin embargo, el problema que tiene es probable que obtenga bucles anidados en una tabla no indexada debido a las pobres estimaciones de cardinalidad asociadas con las variables de la tabla.

select * from @temptableNEW
except
select * from @temptableOLD
OPTION (RECOMPILE)

Podrá tener en cuenta que las tablas tienen 100K filas cada una y dar un plan diferente.

En SQL Server 2012 solo puede agregar índices a las variables de la tabla mediante restricciones. Si los valores son únicos, puede usar

DECLARE @temptableOLD TABLE ([Result1] int UNIQUE CLUSTERED);

para agregar un índice. Si se hace en ambas tablas, el plan (después de agregar la sugerencia de recompilación) probablemente usará una combinación de combinación. Sin ningún índice, esperaría un hash join.

Martin Smith
fuente
Gracias Martin Esta es la respuesta. La OPCIÓN (RECOMPILAR) ayudó (100,000 en 5 minutos), pero el GRUPO ÚNICO en ambas mesas hizo la gran mejora (¡100,000 en 7 segundos!). Solo creé estas tablas para demostrar un problema de la vida real en el que no tengo control sobre la indexación de la tabla en dos servidores SQL diferentes, pero lo manejaré a través de tales variables de tabla.
Will Healey
44
Las #temptablas de @WillHealey tienen muchas ventajas sobre las variables de tabla (estadísticas, paralelismo, indexación más flexible), por lo que si no está usando esto en un contexto donde está restringido a las variables de tabla, también puede probarlas.
Martin Smith