Während des Studiums für die Prüfung 70-433 ist mir aufgefallen, dass Sie auf eine der beiden folgenden Arten einen Deckungsindex erstellen können.
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
-- ODER --
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
Die INCLUDE-Klausel ist für mich neu. Warum sollten Sie es verwenden und welche Richtlinien würden Sie vorschlagen, um zu bestimmen, ob ein Deckungsindex mit oder ohne die INCLUDE-Klausel erstellt werden soll?
SELECT
und für andere nicht? \Sie würden INCLUDE verwenden, um der Blattebene eines nicht gruppierten Index eine oder mehrere Spalten hinzuzufügen. Wenn Sie dies tun, können Sie Ihre Abfragen "abdecken".
Stellen Sie sich vor, Sie müssen die ID, die Abteilungs-ID und den Nachnamen eines Mitarbeiters abfragen.
Wenn Sie zufällig einen nicht gruppierten Index für (EmployeeID, DepartmentID) haben, müssen Sie jetzt, sobald Sie die Mitarbeiter für eine bestimmte Abteilung gefunden haben, eine "Lesezeichen-Suche" durchführen, um den tatsächlichen vollständigen Mitarbeiterdatensatz abzurufen, nur um die Nachname-Spalte zu erhalten . Das kann in Bezug auf die Leistung ziemlich teuer werden, wenn Sie viele Mitarbeiter finden.
Wenn Sie diesen Nachnamen in Ihren Index aufgenommen haben:
Dann sind alle benötigten Informationen auf der Blattebene des nicht gruppierten Index verfügbar. Wenn Sie nur im nicht gruppierten Index suchen und Ihre Mitarbeiter für eine bestimmte Abteilung finden, verfügen Sie über alle erforderlichen Informationen, und die Lesezeichen-Suche für jeden im Index gefundenen Mitarbeiter ist nicht mehr erforderlich -> Sie sparen viel Zeit.
Natürlich können Sie nicht jede Spalte in jeden nicht gruppierten Index aufnehmen. Wenn Sie jedoch Abfragen haben, bei denen nur eine oder zwei Spalten fehlen, die "abgedeckt" werden sollen (und die häufig verwendet werden), kann es sehr hilfreich sein, diese einzuschließen in einen geeigneten nicht gruppierten Index.
quelle
JOIN
Schlüsseln in der Abfrage befinden, und dieINCLUDE
s müssen die Daten sein, die Sie abrufen, aber nicht sortieren.Diese Diskussion fehlt auf dem wichtigen Punkt aus: Die Frage ist nicht , ob die „nicht-Schlüssel-Spalten“ sind besser als umfassen Index -columns oder enthalten -columns.
Die Frage ist, wie teuer es ist, den Include-Mechanismus zu verwenden, um Spalten einzuschließen, die im Index nicht wirklich benötigt werden . (normalerweise nicht Teil der where-Klauseln, aber häufig in selects enthalten). Ihr Dilemma ist also immer:
Wobei: id1, id2 ... idN Spalten sind, die häufig in Einschränkungen verwendet werden, und col1, col2 ... colN Spalten sind, die häufig ausgewählt werden, aber normalerweise nicht in Einschränkungen verwendet werden
(Die Option, alle diese Spalten als Teil des Indexschlüssels einzuschließen, ist einfach immer albern (es sei denn, sie werden auch in Einschränkungen verwendet), da die Wartung immer teurer wäre, da der Index aktualisiert und sortiert werden muss, selbst wenn der "Schlüssel" haben sich nicht geändert).
Verwenden Sie also Option 1 oder 2?
Antwort: Wenn Ihre Tabelle selten aktualisiert wird - meistens eingefügt in / gelöscht von -, ist es relativ kostengünstig, den Include-Mechanismus zu verwenden, um einige "Hot Columns" einzuschließen (die häufig in Auswahlen verwendet werden - aber nicht oft für Einschränkungen verwendet werden) Beim Einfügen / Löschen muss der Index ohnehin aktualisiert / sortiert werden. Daher ist mit dem Speichern einiger zusätzlicher Spalten während der Aktualisierung des Index nur ein geringer zusätzlicher Aufwand verbunden. Der Overhead ist der zusätzliche Speicher und die CPU, die zum Speichern redundanter Informationen im Index verwendet werden.
Wenn die Spalten Sie betrachten hinzufügen , wie enthalten Säulen häufig aktualisiert werden (ohne den Index- Schlüssel -columns aktualisiert) - oder - wenn es so viele von ihnen ist , dass der Index der Nähe einer Kopie Ihrer Tabelle wird - Verwendung der Option 1 Ich würde vorschlagen! Auch wenn sich herausstellt, dass das Hinzufügen bestimmter Include-Spalten keinen Leistungsunterschied ergibt, können Sie die Idee des Hinzufügens überspringen :) Stellen Sie sicher, dass sie nützlich sind!
Die durchschnittliche Anzahl von Zeilen pro gleichen Werten in Schlüsseln (id1, id2 ... idN) kann ebenfalls von Bedeutung sein.
Beachten Sie, dass , wenn eine Spalte - das als ein zusätzlicher ist enthalten -Spalte der Index - in der verwendet wird Einschränkung : Solange der Index kann als solche verwendet werden (basierend auf Beschränkung gegen Index- Schlüssel -columns) - dann SQL Server Matching die Spaltenbeschränkung gegen den Index (Blattknotenwerte), anstatt den teuren Weg um die Tabelle selbst zu gehen.
quelle
Grundlegende Indexspalten werden sortiert, eingeschlossene Spalten werden jedoch nicht sortiert. Dies spart Ressourcen bei der Verwaltung des Index und ermöglicht es dennoch, die Daten in den enthaltenen Spalten bereitzustellen, um eine Abfrage abzudecken. Wenn Sie also Abfragen behandeln möchten, können Sie die Suchkriterien zum Suchen von Zeilen in die sortierten Spalten des Index einfügen, dann aber zusätzliche, unsortierte Spalten mit Nicht-Suchdaten "einschließen". Es hilft definitiv dabei, das Sortieren und Fragmentieren bei der Indexpflege zu reduzieren.
quelle
Die Gründe dafür (einschließlich der Daten in der Blattebene des Index) wurden ausführlich erläutert. Der Grund, warum Sie diesbezüglich zwei Shakes geben, ist, dass SQL Server beim Ausführen Ihrer Abfrage, wenn die zusätzlichen Spalten nicht enthalten sind (neue Funktion in SQL 2005), zum Clustered-Index wechseln muss, um die zusätzlichen Spalten abzurufen Dies nimmt mehr Zeit in Anspruch und erhöht die Belastung des SQL Server-Dienstes, der Festplatten und des Speichers (genauer gesagt des Puffercaches), wenn neue Datenseiten in den Speicher geladen werden, wodurch möglicherweise andere häufig benötigte Daten aus dem Puffercache verschoben werden.
quelle
Eine weitere Überlegung, die ich in den bereits gegebenen Antworten nicht gesehen habe, ist, dass eingeschlossene Spalten Datentypen haben können, die nicht als Indexschlüsselspalten zulässig sind, wie z. B. varchar (max).
Auf diese Weise können Sie solche Spalten in einen Deckungsindex aufnehmen. Ich musste dies kürzlich tun, um eine von nHibernate generierte Abfrage mit vielen Spalten in SELECT mit einem nützlichen Index bereitzustellen.
quelle
Ein Grund,
INCLUDE
Schlüsselspalten vorzuziehen , wenn Sie diese Spalte im Schlüssel nicht benötigen, ist die Dokumentation. Das macht die Entwicklung von Indizes in Zukunft viel einfacher.Betrachten Sie Ihr Beispiel:
Dieser Index ist am besten geeignet, wenn Ihre Abfrage folgendermaßen aussieht:
Natürlich sollten Sie keine Spalten einfügen,
INCLUDE
wenn Sie einen zusätzlichen Vorteil daraus ziehen können, dass sie im Schlüsselteil enthalten sind. Beide der folgenden Abfragen würden tatsächlich diecol2
Spalte im Schlüssel des Index bevorzugen .Nehmen wir an, dass dies nicht der Fall ist und wir dies
col2
in derINCLUDE
Klausel haben, da es einfach keinen Vorteil hat, es im Baumteil des Index zu haben.Schneller Vorlauf einige Jahre.
Sie müssen diese Abfrage optimieren:
Um diese Abfrage zu optimieren, wäre der folgende Index großartig:
Wenn Sie überprüfen, welche Indizes Sie bereits für diese Tabelle haben, ist Ihr vorheriger Index möglicherweise noch vorhanden:
Jetzt wissen Sie das
Col2
undCol3
sind nicht Teil des Indexbaums und werden daher weder zum Eingrenzen des gelesenen Indexbereichs noch zum Ordnen der Zeilen verwendet. Es ist ziemlich sicher,another_column
am Ende des Schlüsselteils des Index (nachcol1
) hinzuzufügen . Es besteht nur ein geringes Risiko, etwas zu beschädigen:Dieser Index wird größer, was immer noch einige Risiken birgt, aber es ist im Allgemeinen besser, bestehende Indizes zu erweitern, als neue einzuführen.
Wenn Sie einen Index ohne hätten
INCLUDE
, könnten Sie nicht wissen, welche Abfragen Sie durch Hinzufügenanother_col
direkt danach brechen würdenCol1
.Was passiert, wenn Sie
another_col
zwischenCol1
und hinzufügenCol2
? Werden andere Fragen leiden?Es gibt andere "Vorteile"
INCLUDE
gegenüber Schlüsselspalten, wenn Sie diese Spalten hinzufügen, um zu vermeiden, dass sie aus der Tabelle abgerufen werden . Ich halte den Dokumentationsaspekt jedoch für den wichtigsten.Zur Beantwortung Ihrer Frage:
Wenn Sie dem Index eine Spalte hinzufügen, um diese Spalte im Index verfügbar zu machen, ohne die Tabelle zu besuchen, fügen Sie sie in die
INCLUDE
Klausel ein.Wenn das Hinzufügen der Spalte zum Indexschlüssel zusätzliche Vorteile bringt (z. B. für
order by
oder weil der Leseindexbereich eingeschränkt werden kann), fügen Sie sie dem Schlüssel hinzu.Eine längere Diskussion dazu können Sie hier lesen:
https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes
quelle
Die Gesamtgröße aller in die Indexdefinition eingefügten Spalten ist begrenzt. Trotzdem musste ich noch nie einen so breiten Index erstellen. Für mich ist der größere Vorteil die Tatsache, dass Sie mehr Abfragen mit einem Index abdecken können, der Spalten enthält, da diese nicht in einer bestimmten Reihenfolge definiert werden müssen. Denken Sie an ist als Index innerhalb des Index. Ein Beispiel wäre die StoreID (wobei StoreID eine geringe Selektivität aufweist, was bedeutet, dass jedes Geschäft vielen Kunden zugeordnet ist) und dann demografische Kundendaten (Nachname, Vorname, Geburtsdatum): Wenn Sie diese Spalten nur in dieser Reihenfolge (StoreID, Nachname) einfügen , Vorname, DOB) können Sie nur effizient nach Kunden suchen, für die Sie StoreID und Nachname kennen.
Wenn Sie andererseits den Index für StoreID definieren und die Spalten LastName, FirstName und DOB einschließen, können Sie im Wesentlichen zwei Such-Index-Prädikate für StoreID ausführen und dann Prädikate für eine der enthaltenen Spalten suchen. Auf diese Weise können Sie alle möglichen Suchpermutationen abdecken, solange diese mit StoreID beginnen.
quelle