Ich habe eine Tabelle mit ein paar Dutzend Zeilen. Es folgt eine vereinfachte Einrichtung
CREATE TABLE #data ([Id] int, [Status] int);
INSERT INTO #data
VALUES (100, 1), (101, 2), (102, 3), (103, 2);
Und ich habe eine Abfrage, die diese Tabelle mit einer Reihe von Tabellenwert-erstellten Zeilen (bestehend aus Variablen und Konstanten) wie verknüpft
DECLARE @id1 int = 101, @id2 int = 105;
SELECT
COALESCE(p.[Code], 'X') AS [Code],
COALESCE(d.[Status], 0) AS [Status]
FROM (VALUES
(@id1, 'A'),
(@id2, 'B')
) p([Id], [Code])
FULL JOIN #data d ON d.[Id] = p.[Id];
Der Ausführungsplan für Abfragen zeigt, dass das Optimierungsprogramm eine FULL LOOP JOIN
Strategie verwendet, die angemessen erscheint, da beide Eingaben nur sehr wenige Zeilen enthalten. Eine Sache, die mir aufgefallen ist (und der ich nicht zustimmen kann), ist, dass TVC-Zeilen gespoolt werden (siehe Bereich des Ausführungsplans im roten Feld).
Warum führt der Optimierer hier die Spool ein, was ist der Grund dafür? Hinter der Spule steckt nichts Komplexes. Sieht aus wie es nicht notwendig ist. Wie kann man es in diesem Fall loswerden, was sind die möglichen Wege?
Der obige Plan wurde am erhalten
Microsoft SQL Server 2014 (SP2-CU11) (KB4077063) - 12.0.5579.0 (X64)
quelle
Antworten:
Die Sache hinter dem Spool ist keine einfache Tabellenreferenz, die einfach dupliziert werden könnte, wenn die linke Join- / Antisemi- Join- Alternative generiert wird.
Es mag ein wenig wie eine Tabelle aussehen (Constant Scan), aber für den Optimierer * ist es eine
UNION ALL
der separaten Zeilen in derVALUES
Klausel.Die zusätzliche Komplexität reicht aus, damit der Optimierer die Quellzeilen spoolen und wiedergeben kann und die Spool später nicht durch ein einfaches "table get" ersetzt. Die anfängliche Umwandlung vom vollständigen Join sieht beispielsweise folgendermaßen aus:
Beachten Sie die zusätzlichen Spools, die durch die allgemeine Transformation eingeführt wurden. Spulen über einem einfachen Tisch werden später von der Regel aufgeräumt
SpoolGetToGet
.Wenn das Optimierungsprogramm eine entsprechende
SpoolConstGetToConstGet
Regel hätte, könnte es im Prinzip so funktionieren, wie Sie möchten.Verwenden Sie eine reale Tabelle (temporär oder variabel) oder schreiben Sie die Umwandlung von der vollständigen Verknüpfung manuell, zum Beispiel:
Plan für manuelles Umschreiben:
Dies hat geschätzte Kosten von 0,0067201 Einheiten, verglichen mit 0,0203412 Einheiten für das Original.
* Kann
LogOp_UnionAll
im konvertierten Baum (TF 8605) als beobachtet werden . Im Eingabebaum (TF 8606) ist es einLogOp_ConstTableGet
. Der konvertierte Baum zeigt den Baum der Ausdruckselemente des Optimierers nach dem Parsen, Normalisieren, Algebrisieren, Binden und einigen anderen vorbereitenden Arbeiten. Der Eingangsbaum zeigt die Elemente nach der Konvertierung in Negationsnormalform (NNF convert), Laufzeitkonstante kollabiert, und ein paar anderen Bits und Bob. Die NNF-Konvertierung beinhaltet unter anderem Logik, um logische Vereinigungen zu reduzieren und gemeinsame Tabellen zu erhalten.quelle
Der Tabellenspool erstellt einfach eine Tabelle aus den beiden in der
VALUES
Klausel enthaltenen Tupelsätzen.Sie können den Spool eliminieren, indem Sie diese Werte zuerst in eine temporäre Tabelle einfügen:
Wenn Sie sich den Ausführungsplan für Ihre Abfrage ansehen, sehen Sie, dass die Ausgabeliste zwei Spalten enthält, die das
Union
Präfix verwenden. Dies ist ein Hinweis darauf, dass der Spool eine Tabelle aus einer unionsgeeigneten Quelle erstellt:Das
FULL OUTER JOIN
erfordert, dass SQL Serverp
zweimal auf die Werte zugreift, einmal für jede "Seite" des Joins. Durch das Erstellen einer Spool können die resultierenden inneren Schleifen auf die Spooldaten zugreifen.Interessanterweise verwendet SQL Server keinen Spool , wenn Sie die Zeichen
FULL OUTER JOIN
mitLEFT JOIN
undRIGHT JOIN
undUNION
die Ergebnisse zusammen ersetzen .Beachten Sie, dass ich nicht vorschlage, die
UNION
obige Abfrage zu verwenden. Bei größeren Eingaben ist die Leistung möglicherweise nicht effizienter als die einfache, dieFULL OUTER JOIN
Sie bereits haben.quelle