Ich stelle diese Frage, um das Verhalten des Optimierers besser zu verstehen und die Grenzen der Index-Spools zu verstehen. Angenommen, ich lege Ganzzahlen von 1 bis 10000 auf 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 Nested 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. Joins mit verschachtelten Schleifen sind oft keine gute Wahl, wenn beide Tabellen keine relevanten Indizes haben. Hier ist der Plan:
Die Abfrage auf meinem Computer dauert 13 Sekunden, wenn 100000000 Zeilen vom Tabellenspool abgerufen wurden. Ich verstehe jedoch nicht, warum die Abfrage langsam sein muss. Das Abfrageoptimierungsprogramm kann Indizes im laufenden Betrieb über Index-Spools erstellen . Diese Abfrage scheint ein perfekter Kandidat für eine Index-Spool zu sein.
Die folgende Abfrage gibt dieselben Ergebnisse wie die erste zurück, verfügt über eine Index-Spool und wird in weniger als einer Sekunde beendet:
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);
Diese Abfrage hat auch eine Index-Spool 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);
Warum hat die ursprüngliche Abfrage keine Index-Spool? Gibt es eine Reihe von dokumentierten oder undokumentierten Hinweisen oder Ablaufverfolgungsflags, die eine Index-Spool ergeben? Ich habe diese verwandte Frage gefunden , aber sie beantwortet meine Frage nicht vollständig und ich kann das mysteriöse Ablaufverfolgungsflag nicht für diese Abfrage verwenden.