W poniższych zapytaniach szacuje się, że oba plany wykonania wykonają 1000 wyszukiwań na unikalnym indeksie.
Poszukiwania są sterowane przez uporządkowane skanowanie w tej samej tabeli źródłowej, więc najwyraźniej powinno się kończyć szukanie tych samych wartości w tej samej kolejności.
Obie zagnieżdżone pętle mają <NestedLoops Optimized="false" WithOrderedPrefetch="true">
Czy ktoś wie, dlaczego to zadanie kosztuje w pierwszym planie 0,172434, a w drugim 3.01702?
(Powodem pytania jest to, że pierwsze zapytanie zostało zasugerowane jako optymalizacja ze względu na pozornie znacznie niższy koszt planu. Właściwie to wygląda na to, że działa więcej, ale ja tylko próbuję wyjaśnić tę rozbieżność. .)
Ustawiać
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;
Zapytanie 1 Link „Wklej 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;
Zapytanie 2 Link „Wklej 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;
Zapytanie 1
Zapytanie 2
Powyższe zostało przetestowane na SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
@Joe Obbish podkreśla w komentarzach, że prostsze byłoby repro
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;
W przypadku tabeli pomostowej rzędu 1000 oba powyższe nadal mają ten sam kształt planu z zagnieżdżonymi pętlami, a plan bez tabeli pochodnej wydaje się tańszy, ale w przypadku tabeli pomostowej rzędu 10 000 i tej samej tabeli docelowej jak powyżej różnica kosztów zmienia plan kształt (z pełnym skanowaniem i łączeniem scalającym, które wydają się względnie bardziej atrakcyjne niż kosztowne poszukiwania), pokazując, że ta rozbieżność kosztów może mieć inne konsekwencje niż tylko utrudnianie porównywania planów.