Zwei Spalten mit und ohne Index in der where-Klausel - Funktionsweise des Index

7

Ich führe eine Abfrage unter SQL Server 2008 aus:

SELECT col1
FROM table1
WHERE col2=val2 AND col3=val3

Hier hat col2 einen nicht gruppierten Index, col1 ist der PRIMARY KEYund col3 hat keinen Index. Der Ausführungsplan für Abfragen ähnelt diesem. Geben Sie hier die Bildbeschreibung ein

Ich möchte wissen, wie die Abfrageausführung hier funktioniert. Aus dem Ausführungsplan kann ich eine Indexsuche für 'col2' und eine Schlüsselsuche für 'col3' sehen (parallel dargestellt).

  • Wird es alle Zeilen abrufen, die der Bedingung 'col2 = val2' entsprechen, und nach der anderen Bedingung suchen?
  • Warum werden diese beiden Indexsuchen und Schlüsselsuchen im Ausführungsplan parallel angezeigt?
  • Wird immer der verfügbare Index für 'col2' verwendet, wenn ein großer Datensatz berücksichtigt wird und davon ausgegangen wird, dass fast alle Einträge in 'col2' eindeutig sind?
Rahul Raghavan
quelle

Antworten:

12

Ich möchte wissen, wie die Abfrageausführung hier funktioniert

Das allgemeine Ausführungsmodell ist eine Pipeline, in der jeder Iterator jeweils eine Zeile zurückgibt. Die Ausführung beginnt am Root-Iterator (ganz links, SELECTin Ihrem Beispiel gekennzeichnet).

Nach der Initialisierung fordert der Root-Iterator eine Zeile von seinem unmittelbaren untergeordneten Element usw. in der Kette an, bis ein Iterator gefunden wird, der eine Zeile zurückgeben kann. Dies führt die Kette zurück zum Stamm, wo sie für den Versand an den Client in die Warteschlange gestellt wird. Das ist eine sehr vereinfachte Übersicht, für weitere Details siehe:

Wird es alle Zeilen abrufen, die der Bedingung 'col2 = val2' entsprechen, und nach der anderen Bedingung suchen?

Bei der Suche nach nicht gruppierten Indizes wird eine übereinstimmende Zeile gefunden col2=val2. Es kann col2 und col1 zurückgeben (siehe Ausgabeliste), da col1 im Index vorhanden ist (da der Primärschlüssel in diesem Fall geclustert ist).

Diese Zeile wird an den Join der verschachtelten Schleifen übergeben, der dann die Steuerung an die Schlüsselsuche übergibt. Die Suche verwendet den Wert col1 , um im Clustered-Index-B-Baum nach dem Wert von col3 in dieser Zeile zu suchen . Der Wert wird gegen das Prädikat getestet col3=val3und nur zurückgegeben, wenn er übereinstimmt.

Wenn eine Übereinstimmung vorliegt, wird die Zeile (c1, c2, c3) die Kette entlang geleitet und zur Übertragung an den Client in die Warteschlange gestellt. Wenn die Steuerung den Baum wieder herabsteigt, führt jede neue Übereinstimmung für col2 im nicht gruppierten Index zu einer Wiederholung des Joins verschachtelter Schleifen -> Nachschlagen -> Zeilenzyklus zurückgeben. Sobald die nicht gruppierte Indexsuche keine Zeilen mehr enthält, wird der Prozess abgeschlossen, wenn die Steuerung das nächste Mal zum Root-Iterator zurückkehrt.

Warum werden diese beiden Indexsuchen und Schlüsselsuchen im Ausführungsplan parallel angezeigt?

So ist der grafische Plan aufgebaut. In den obigen Links und in der Diskussion finden Sie Informationen zum korrekten Verständnis des Ausführungsprozesses im Detail.

Wird immer der verfügbare Index für 'col2' verwendet, wenn ein großer Datensatz berücksichtigt wird und davon ausgegangen wird, dass fast alle Einträge in 'col2' eindeutig sind?

Sehr wahrscheinlich ja. Der Optimierer trifft eine kostenbasierte Wahl zwischen den verfügbaren Strategien. Da nur sehr wenige Übereinstimmungen erwartet werden, bewertet der Optimierer normalerweise eine nicht gruppierte Indexsuche mit einer Suche als die billigste Option. Eine Ausnahme tritt auf, wenn die Tabelle sehr klein ist. In diesem Fall ist das Scannen des Clustered-Index und das Anwenden beider Prädikate auf jede Zeile wahrscheinlich am billigsten.

Als letzte Anmerkung lautet ein nicht gruppierter Index, der die Suche vermeiden würde:

CREATE [UNIQUE] NONCLUSTERED INDEX [dbo.table1 col2,col3 (col1)]
ON dbo.table1 (col2, col3)
INCLUDE (col1);

Es sollte angegeben werden, UNIQUEob dies für (col2, col3) zutrifft.

Paul White 9
quelle