Was ist der Unterschied zwischen einem Tabellenscan und einem Clustered-Index-Scan?

70

Warum ist ein Clustered Index Scan angeblich besser, da sowohl ein Table Scanals auch ein im Clustered Index ScanWesentlichen alle Datensätze in der Tabelle scannen?

Als Beispiel - Was ist der Leistungsunterschied zwischen den folgenden, wenn es viele Datensätze gibt?:

declare @temp table(
    SomeColumn varchar(50)
)

insert into @temp
select 'SomeVal'

select * from @temp

-----------------------------

declare @temp table(
    RowID int not null identity(1,1) primary key,
    SomeColumn varchar(50)
)

insert into @temp
select 'SomeVal'

select * from @temp
Seibar
quelle

Antworten:

78

In einer Tabelle ohne Clustered-Index (eine Heap-Tabelle) sind Datenseiten nicht miteinander verknüpft. Das Durchlaufen von Seiten erfordert daher eine Suche in der Indexzuordnungszuordnung .

Bei einer gruppierten Tabelle sind die Datenseiten jedoch in einer doppelt verknüpften Liste verknüpft, wodurch sequentielle Scans etwas schneller ausgeführt werden. Natürlich im Austausch haben Sie den Aufwand für den Umgang mit den Datenseiten in Ordnung zu halten auf INSERT, UPDATEund DELETE. Eine Heap-Tabelle erfordert jedoch ein zweites Schreiben in das IAM.

Wenn Ihre Abfrage einen RANGEOperator hat (z. B. SELECT * FROM TABLE WHERE Id BETWEEN 1 AND 100:), ist eine gruppierte Tabelle (in einer garantierten Reihenfolge) effizienter, da sie die Indexseiten verwenden könnte, um die relevanten Datenseiten zu finden. Ein Heap müsste alle Zeilen scannen, da er sich nicht auf die Reihenfolge verlassen kann.

Und natürlich können Sie mit einem Clustered-Index einen CLUSTERED INDEX SEEK durchführen, der für die Leistung ziemlich optimal ist. Ein Heap ohne Indizes würde immer zu einem Tabellenscan führen.

Damit:

  • Bei Ihrer Beispielabfrage, bei der Sie alle Zeilen auswählen, besteht der einzige Unterschied in der doppelt verknüpften Liste, die ein Clustered-Index verwaltet. Dies sollte Ihre Clustertabelle nur ein kleines bisschen schneller machen als einen Heap mit einer großen Anzahl von Zeilen.

  • Bei einer Abfrage mit einer WHEREKlausel, die (zumindest teilweise) vom Clustered-Index erfüllt werden kann, haben Sie aufgrund der Reihenfolge die Nase vorn - Sie müssen also nicht die gesamte Tabelle scannen.

  • Bei einer Abfrage, die vom Clustered-Index nicht erfüllt wird, sind Sie ziemlich ausgeglichen. Der einzige Unterschied besteht in der doppelt verknüpften Liste für das sequentielle Scannen. In beiden Fällen sind Sie nicht optimal.

  • Für INSERT, UPDATEund DELETEein Haufen gewinnen kann oder nicht. Der Heap muss die Reihenfolge nicht aufrechterhalten, erfordert jedoch ein zweites Schreiben in das IAM. Ich denke, der relative Leistungsunterschied wäre vernachlässigbar, aber auch ziemlich datenabhängig.

Microsoft hat ein Whitepaper, das einen Clustered-Index mit einem äquivalenten Nicht-Clustered-Index auf einem Heap vergleicht (nicht genau das gleiche wie oben beschrieben, aber geschlossen). Ihre Schlussfolgerung besteht im Wesentlichen darin, einen Clustered-Index für alle Tabellen zu erstellen. Ich werde mein Bestes tun, um ihre Ergebnisse zusammenzufassen (wieder beachten Sie, dass sie hier wirklich einen nicht gruppierten Index mit einem gruppierten Index vergleichen - aber ich denke, dass es relativ vergleichbar ist):

  • INSERT Leistung: Der Clustered-Index gewinnt aufgrund des zweiten für einen Heap erforderlichen Schreibvorgangs um ca. 3%.
  • UPDATE Leistung: Der Clustered-Index gewinnt aufgrund der zweiten für einen Heap erforderlichen Suche um ca. 8%.
  • DELETE Leistung: Der Clustered-Index gewinnt aufgrund der zweiten erforderlichen Suche und der zweiten Löschung aus dem IAM für einen Heap um ca. 18%.
  • Einzelleistung SELECT: Der Clustered-Index gewinnt aufgrund der zweiten Suche, die für einen Heap erforderlich ist, um etwa 16%.
  • Bereichsleistung SELECT: Der Clustered-Index gewinnt aufgrund der zufälligen Reihenfolge für einen Heap um etwa 29%.
  • Gleichzeitig INSERT: Die Heap-Tabelle gewinnt unter Last aufgrund von Seitenteilungen für den Clustered-Index um 30%.
Mark Brackett
quelle
2
Diese Frage kam mir heute in den Sinn. Danke @Terrapin, dass du das gefragt hast und danke an @Marc, dass du es so gut beantwortet hast!
Höhepunkt
2
MS Exam 70461 Abfragen von Microsoft SQL Server 2012 - Kapitel 15 In Lektion 1 wird ausführlich ausgenutzt.
Jewgraf Andrejewitsch Schiwago
Ich kann anscheinend nicht den vermeintlichen Schub erreichen, der durch Ihre Aussage angezeigt wird: "Bei einer Abfrage mit einer WHERE-Klausel, die vom Clustered-Index (zumindest teilweise) erfüllt werden kann, werden Sie aufgrund der Reihenfolge die Nase vorn haben - Sie müssen also nicht die gesamte Tabelle scannen. " Ich habe eine Tabelle mit 10 Millionen Zeilen. SELECT ID FROM Customer WHERE ID> X wird in der gleichen Zeit ausgeführt, unabhängig davon, ob ich einen Clustered-Index für Id habe oder nicht. Woher? Ich kann sehen, wie es sich vom Tabellenscan zum Clustered-Index-Scan ändert.
Mattias Nordqvist
2
@MattiasNordqvist - Wenn Sie nur auf die benötigte Zeit schauen, machen Sie es falsch. Aufgrund von Caching, gleichzeitigem Zugriff, CPU- und Festplattenzeit usw. ist es schwierig, MS-SQL allein pünktlich zu optimieren. Schauen Sie in SET STATISTICS IO ON nach, um zu überprüfen, ob Ihre Festplatte gelesen wurde und woher der Boost kommen würde. Zweitens hängt es von der Anzahl der zurückgegebenen Zeilen ab. Wenn der Prozentsatz hoch genug ist, kann der Optimierer möglicherweise stattdessen einen Lese- + Filter auswählen.
Mark Brackett
4

http://msdn.microsoft.com/en-us/library/aa216840(SQL.80).aspx

Der logische und physische Operator Clustered Index Scan durchsucht den in der Spalte Argument angegebenen Clustered-Index. Wenn ein optionales WHERE :() -Prädikat vorhanden ist, werden nur die Zeilen zurückgegeben, die das Prädikat erfüllen. Wenn die Spalte Argument die ORDERED-Klausel enthält, hat der Abfrageprozessor angefordert, dass die Ausgabe der Zeilen in der Reihenfolge zurückgegeben wird, in der der Clustered-Index sie sortiert hat. Wenn die ORDERED-Klausel nicht vorhanden ist, scannt die Speicher-Engine den Index auf optimale Weise (ohne Garantie für die zu sortierende Ausgabe).

http://msdn.microsoft.com/en-us/library/aa178416(SQL.80).aspx

Der logische und physische Operator "Tabellenscan" ruft alle Zeilen aus der in der Spalte "Argument" angegebenen Tabelle ab. Wenn in der Spalte Argument ein WHERE :() -Prädikat angezeigt wird, werden nur die Zeilen zurückgegeben, die das Prädikat erfüllen.

Stu
quelle
-2

Ein Tabellenscan muss jede einzelne Zeile der Tabelle untersuchen. Der Clustered-Index-Scan muss nur den Index scannen. Es wird nicht jeder Datensatz in der Tabelle gescannt. Darum geht es eigentlich bei Indizes.

DrPizza
quelle
8
-1 Das ist falsch. Die Blattebene des Clustered-Index ist die Tabelle.
Martin Smith