it-swarm.com.de

Warum verwendet diese Abfrage keine Indexspool?

Ich stelle diese Frage, um das Verhalten des Optimierers besser zu verstehen und die Grenzen um Indexspulen zu verstehen. Angenommen, ich setze ganze Zahlen von 1 bis 10000 in einen Haufen:

CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;

INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Und erzwinge einen verschachtelten Loop-Join mit MAXDOP 1:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);

Dies ist eine ziemlich unfreundliche Aktion gegenüber SQL Server. Verschachtelte Schleifenverknüpfungen sind oft keine gute Wahl, wenn beide Tabellen keine relevanten Indizes haben. Hier ist der Plan:

(bad query

Die Abfrage dauert auf meinem Computer 13 Sekunden, wobei 100000000 Zeilen von der Tabellenspool abgerufen werden. Ich verstehe jedoch nicht, warum die Abfrage langsam sein muss. Das Abfrageoptimierungsprogramm kann Indizes im laufenden Betrieb über Indexspools erstellen. Diese Abfrage scheint ein perfekter Kandidat für eine Indexspool zu sein.

Die folgende Abfrage gibt dieselben Ergebnisse wie die erste zurück, verfügt über eine Indexspool und endet in weniger als einer Sekunde:

SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);

(workaround 1

Diese Abfrage hat auch eine Indexspool und endet in weniger als einer Sekunde:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);

(workaround 2

Warum hat die ursprüngliche Abfrage keine Indexspool? Gibt es eine Reihe von dokumentierten oder nicht dokumentierten Hinweisen oder Ablaufverfolgungsflags, die ihm eine Indexspool geben? Ich habe diese verwandte Frage gefunden, aber meine Frage wird nicht vollständig beantwortet, und ich kann das mysteriöse Trace-Flag nicht für diese Abfrage verwenden.

23
Joe Obbish

Wie Sie wissen, ist die Suche des Optimierers nicht vollständig. Es werden Dinge ausprobiert, die im Kontext sinnvoll sind und die sich bei echten Anfragen häufig auszahlen. Das Erzwingen einer Schleifenverknüpfung zwischen zwei einspaltigen nicht indizierten Heap-Tabellen ist kein solches Szenario. Das heißt, hier sind einige Details:

SQL Server transformiert gerne für Verknüpfungen frühzeitig, da es mehr Tricks mit Verknüpfungen kennt. Später wird möglicherweise untersucht, ob der Join wieder in einen Apply konvertiert werden kann. Das nterschied zwischen den beiden sind korrelierte Parameter (äußere Referenzen). Gilt sinnvoll, wenn auf der Innenseite ein geeigneter Index vorhanden ist. Ihr Beispiel enthält keine Indizes, sodass der Optimierer nicht überzeugt ist, die Übersetzung in eine Anwendung zu untersuchen.

Bei einem einfachen (nicht zutreffenden) Join wird das Join-Prädikat für den Join-Operator anstelle von äußeren Referenzen verwendet. Die Spool-Optimierung für eine Nichtanwendung ist normalerweise eine Lazy-Table-Spool, da auf der Innenseite nur beim Join kein Prädikat vorhanden ist.

Der Optimierer erwägt nicht, einen Index im laufenden Betrieb zu erstellen, um eine Anwendung zu ermöglichen. Vielmehr ist die Reihenfolge der Ereignisse normalerweise umgekehrt: Transformieren, um anzuwenden, da ein guter Index vorhanden ist.

Sie können manchmal eine Anwendung anstelle eines Joins fördern, indem Sie die Syntax APPLY in Ihrer Abfrage verwenden. Das undokumentierte Ablaufverfolgungsflag 9114 kann dabei helfen, indem es den Optimierer davon abhält, eine logische Anwendung auf eine Verknüpfung im Voraus zu übersetzen. Zum Beispiel:

SELECT * 
FROM dbo.X_1000 AS a
CROSS APPLY (SELECT * FROM dbo.X_1000 AS b WHERE b.ID = a.ID) AS b
OPTION (QUERYTRACEON 9114);

(Spool plan

Eine Indexspule wird zum Anwenden bevorzugt, da die äußere Referenz bedeutet, dass die Auswahl auf der Innenseite des Joins angewendet wird. Sie werden dies oft über SelToIndexOnTheFly sehen, aber es gibt andere Pfade. Siehe meinen Artikel The Eager Index Spool und The Optimizer .

21
Paul White 9