Welche Kostenfaktoren fließen in den Optimierer ein, der verschiedene Spulentypen auswählt?


15

Spoolum

In SQL Server gibt es verschiedene Arten von Spools. Die beiden, die mich interessieren, sind Table Spool s und Index Spools , abgesehen von Änderungsabfragen .

Bei schreibgeschützten Abfragen, insbesondere auf der Innenseite eines Nested Loops-Joins, wird möglicherweise entweder ein Tabellen- oder ein Index-Spool verwendet, um die E / A-Leistung zu verringern und die Abfrageleistung zu verbessern. Diese Spulen können Eager oder Lazy sein . Genau wie du und ich.

Meine Fragen sind:

  • Welche Faktoren spielen bei der Auswahl von Table vs. Index Spool eine Rolle?
  • Welche Faktoren bestimmen die Wahl zwischen Eager und Lazy Spools?

Antworten:


12

Dies ist ein wenig weit gefasst, aber ich denke, ich verstehe die wahre Frage und werde entsprechend antworten. Ich werde nur über Tabelle vs. Index-Spool sprechen. Ich denke, es ist nicht ganz richtig, dort eine Wahl zwischen Tabellen- und Index-Spools zu sehen. Wie Sie wissen, ist es in einem einzelnen Teilbaum möglich, eine Index- oder Tabellenspule oder sowohl eine Index- als auch eine Tabellenspule abzurufen. Ich glaube, es ist im Allgemeinen richtig zu sagen, dass Sie eine Index-Spool unter den folgenden Bedingungen erhalten:

  1. Das Abfrageoptimierungsprogramm hat einen Grund, einen Join in einen Apply umzuwandeln
  2. Das Abfrageoptimierungsprogramm führt die Transformation für die Anwendung aus
  3. Das Abfrageoptimierungsprogramm verwendet die Regel, um einen Index-Spool hinzuzufügen (mindestens muss der Index-Spool sicher sein).
  4. Der Plan mit der Index-Spool ist ausgewählt

Sie können die meisten davon mit einfachen Demos sehen. Beginnen Sie mit dem Erstellen eines Paares von Heaps:

DROP TABLE IF EXISTS dbo.X_10000_VARCHAR_901;
CREATE TABLE dbo.X_10000_VARCHAR_901 (ID VARCHAR(901) NOT NULL);

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


DROP TABLE IF EXISTS dbo.X_10000_VARCHAR_800;
CREATE TABLE dbo.X_10000_VARCHAR_800 (ID VARCHAR(800) NOT NULL);

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

Bei der ersten Abfrage gibt es nichts zu suchen:

SELECT *
FROM dbo.X_10000_VARCHAR_901 a
CROSS JOIN dbo.X_10000_VARCHAR_901 b
OPTION (MAXDOP 1);

Es gibt also keinen Grund für das Optimierungsprogramm, den Join in eine Anwendung umzuwandeln. Aus Kostengründen erhalten Sie eine Tabellenspule. Diese Abfrage besteht also den ersten Test nicht.

Bildbeschreibung hier eingeben

Für die nächste Abfrage ist zu erwarten, dass das Optimierungsprogramm einen Grund hat, eine Anwendung in Betracht zu ziehen:

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

Aber es soll nicht sein:

Bildbeschreibung hier eingeben

Diese Abfrage besteht den zweiten Test nicht. Eine vollständige Erklärung finden Sie hier . Zitat des relevantesten Teils:

Das Optimierungsprogramm erwägt nicht, einen Index im laufenden Betrieb zu erstellen, um eine Anwendung zu ermöglichen. Vielmehr ist die Reihenfolge der Ereignisse normalerweise umgekehrt: Transformiere, um anzuwenden, weil ein guter Index existiert.

Ich kann die Abfrage umschreiben, um das Optimierungsprogramm zu ermutigen, sich zu bewerben:

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

Es gibt aber noch keine Index-Spool:

Bildbeschreibung hier eingeben

Diese Abfrage besteht den dritten Test nicht. In SQL Server 2014 war die Länge des Indexschlüssels auf 900 Byte begrenzt. Dies wurde in SQL Server 2016 erweitert, jedoch nur für nicht gruppierte Indizes. Der Index für eine Spool ist ein Clustered-Index, sodass das Limit bei 900 Bytes bleibt . In jedem Fall kann die Index-Spool-Regel nicht angewendet werden, da dies zu einem Fehler bei der Abfrageausführung führen kann.

Das Reduzieren der Datentyplänge auf 800 liefert schließlich einen Plan mit einer Index-Spool:

Bildbeschreibung hier eingeben

Es überrascht nicht, dass der Index-Spool-Plan erheblich günstiger ist als ein Plan ohne Spool: 89,7603 Einheiten gegenüber 598,832 Einheiten. Sie können den Unterschied anhand des undokumentierten QUERYRULEOFF BuildSpoolAbfragehinweises erkennen:

Bildbeschreibung hier eingeben

Dies ist keine vollständige Antwort, aber es ist hoffentlich etwas von dem, wonach Sie gesucht haben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.