En las consultas a continuación, se estima que ambos planes de ejecución realizan 1,000 búsquedas en un índice único.
Las búsquedas son conducidas por una exploración ordenada en la misma tabla fuente, por lo que aparentemente deberían terminar buscando los mismos valores en el mismo orden.
Ambos bucles anidados tienen <NestedLoops Optimized="false" WithOrderedPrefetch="true">
¿Alguien sabe por qué esta tarea tiene un costo de 0.172434 en el primer plan pero 3.01702 en el segundo?
(La razón de la pregunta es que la primera consulta me fue sugerida como una optimización debido al costo aparentemente mucho más bajo del plan. En realidad, me parece que hace más trabajo pero solo estoy tratando de explicar la discrepancia ... .)
Preparar
CREATE TABLE dbo.Target(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);
CREATE TABLE dbo.Staging(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);
INSERT INTO dbo.Target
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1,
master..spt_values v2;
INSERT INTO dbo.Staging
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1;
Consulta 1 enlace "Pegar el plan"
WITH T
AS (SELECT *
FROM Target AS T
WHERE T.KeyCol IN (SELECT S.KeyCol
FROM Staging AS S))
MERGE T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
INSERT ( KeyCol, OtherCol )
VALUES(S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
UPDATE SET T.OtherCol = S.OtherCol;
Consulta 2 enlace "Pegar el plan"
MERGE Target T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
INSERT ( KeyCol, OtherCol )
VALUES( S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
UPDATE SET T.OtherCol = S.OtherCol;
Consulta 1
Consulta 2
Lo anterior se probó en SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
@Joe Obbish señala en los comentarios que una reproducción más simple sería
SELECT *
FROM staging AS S
LEFT OUTER JOIN Target AS T
ON T.KeyCol = S.KeyCol;
vs
SELECT *
FROM staging AS S
LEFT OUTER JOIN (SELECT * FROM Target) AS T
ON T.KeyCol = S.KeyCol;
Para la tabla de etapas de 1,000 filas, las dos anteriores tienen la misma forma de plan con bucles anidados y el plan sin que la tabla derivada parezca más barata, pero para una tabla de etapas de 10,000 filas y la misma tabla de destino que la anterior, la diferencia de costos cambia el plan La forma (con un escaneo completo y una combinación que parece relativamente más atractiva que las búsquedas costosas) que muestra esta discrepancia de costos puede tener otras implicaciones además de dificultar la comparación de planes.