Ich habe gelesen Clustered
und Non Clustered Indexes
.
Clustered Index
- Es enthält Datenseiten. Das bedeutet, dass die vollständigen Zeileninformationen in der Clustered-Index-Spalte enthalten sind.
Non Clustered Index
- Es enthält nur die Zeilenlokalisierungsinformationen in Form einer Spalte mit gruppiertem Index (falls verfügbar) oder den Dateiindikator + Seitenzahl + Gesamtanzahl der Zeilen auf einer Seite. Dies bedeutet, dass die Abfrage-Engine einen zusätzlichen Schritt ausführen muss, um die tatsächlichen Daten zu lokalisieren.
Abfrage - Wie kann ich den Unterschied in der Leistung mit Hilfe eines praktischen Beispiels überprüfen , da wir wissen , dass die Tabelle nur eine haben kann Clustered Index
und bietet sorting
an dem Clustered Index Column
und Non Clustered Index
bietet nicht sorting
und 999 unterstützen kann Non Clustered Indexes
in SQL Server 2008
in und 249 SQL Server 2005
.
Antworten:
Sehr gute Frage, da es sich um ein so wichtiges Konzept handelt. Dies ist jedoch ein großes Thema, und ich zeige Ihnen, dass es sich um eine Vereinfachung handelt, damit Sie die grundlegenden Konzepte verstehen können.
Erstens, wenn Sie Clustered Index Think Table sehen . Wenn eine Tabelle in SQL Server keinen Clustered-Index enthält, handelt es sich um einen Heap. Durch das Erstellen eines Clustered-Index für die Tabelle wird die Tabelle tatsächlich in eine Struktur vom Typ B-Tree umgewandelt. Ihr Clustered-Index IST Ihre Tabelle, er ist nicht von der Tabelle getrennt
Haben Sie sich jemals gefragt, warum Sie nur einen Clustered-Index haben können? Wenn wir zwei Clustered-Indizes hätten, bräuchten wir zwei Kopien der Tabelle. Es enthält schließlich die Daten.
Ich werde versuchen, dies anhand eines einfachen Beispiels zu erklären.
HINWEIS: Ich habe die Tabelle in diesem Beispiel erstellt und sie mit über 3 Millionen zufälligen Einträgen gefüllt. Dann liefen die eigentlichen Abfragen und fügten die Ausführungspläne hier ein.
Was Sie wirklich verstehen müssen, ist die O-Notation oder die betriebliche Effizienz . Angenommen, Sie haben die folgende Tabelle.
Hier haben wir also eine Basistabelle mit einem gruppierten Schlüssel auf CustomerID (der Primärschlüssel wird standardmäßig gruppiert). Somit wird die Tabelle basierend auf dem Primärschlüssel CustomerID angeordnet / geordnet. Die Zwischenebenen enthalten die CustomerID-Werte. Die Datenseiten enthalten die gesamte Zeile, also die Tabellenzeile.
Wir erstellen auch einen nicht gruppierten Index für das Feld Kundenname. Der folgende Code wird es tun.
In diesem Index finden Sie also auf den Datenseiten / Knoten auf Blattebene einen Zeiger auf die Zwischenebenen im Clustered-Index. Der Index ist um das Feld Kundenname angeordnet / geordnet. Somit enthält die Zwischenebene die CustomerName-Werte und die Blattebene enthält den Zeiger (diese Zeigerwerte sind tatsächlich die Primärschlüsselwerte oder die CustomerID-Spalte).
Richtig also, wenn wir folgende Abfrage ausführen:
SQL liest den Clustered-Index wahrscheinlich über eine Suchoperation. Eine Suchoperation ist eine binäre Suche, die viel effizienter ist als eine Abtastung, die eine sequentielle Suche ist. In unserem obigen Beispiel wird der Index gelesen und durch die Verwendung einer binären Such-SQL können die Daten entfernt werden, die nicht den von uns gesuchten Kriterien entsprechen. Den Abfrageplan finden Sie im angehängten Screenshot.
Die Anzahl der Operationen oder die O-Notation für die Suchoperation ist also wie folgt:
Es sind also zwei Operationen. Wenn wir jedoch die folgende Abfrage ausführen:
SQL verwendet jetzt den nicht gruppierten Index für den Kundennamen, um die Suche durchzuführen. Da es sich jedoch um einen nicht gruppierten Index handelt, enthält dieser nicht alle Daten in der Zeile.
Daher durchsucht SQL die Zwischenebenen, um die passenden Datensätze zu finden, und durchsucht anschließend den geclusterten Index (auch als Tabelle bezeichnet) erneut nach den zurückgegebenen Werten, um die tatsächlichen Daten abzurufen. Das klingt verwirrend, ich weiß, aber lies weiter und alles wird klar.
Da unser nicht gruppierter Index nur das CustomerName-Feld (die in den Zwischenknoten gespeicherten indizierten Feldwerte) und den Zeiger auf die Daten enthält, bei denen es sich um die CustomerID handelt, enthält der Index keinen Datensatz des CustomerSurname. Der Kundenname muss aus dem gruppierten Index oder der gruppierten Tabelle abgerufen werden.
Beim Ausführen dieser Abfrage erhalte ich den folgenden Ausführungsplan:
In der obigen Abbildung sind zwei wichtige Punkte zu beachten
Warum schlägt SQL den Index für CustomerName erneut vor? Nun, da der Index nur die CustomerID und den CustomerName enthält, muss SQL noch den CustomerSurname aus der Tabelle / den Clustered-Indizes finden.
Wenn wir den Index erstellen und die Spalte CustomerSurname in den Index aufnehmen, kann SQL die gesamte Abfrage erfüllen, indem nur der nicht gruppierte Index gelesen wird. Aus diesem Grund schlägt SQL vor, meinen nicht gruppierten Index zu ändern.
Hier sehen Sie die zusätzliche Operation, die SQL ausführen muss, um die CustomerSurname-Spalte vom gruppierten Schlüssel abzurufen
Somit ist die Anzahl der Operationen wie folgt:
Das sind 4 Operationen, um die Werte herauszufinden. Doppelte Anzahl an Operationen im Vergleich zum Lesen des Clustered-Index. Das zeigt Ihnen, dass Ihr Clustered-Index Ihr leistungsstärkster Index ist, da er alle Daten enthält.
Also nur um einen letzten Punkt zu verdeutlichen. Warum sage ich, dass der Zeiger im nicht gruppierten Index der Primärschlüsselwert ist? Um zu demonstrieren, dass die Knoten auf Blattebene des nicht gruppierten Index den Primärschlüsselwert enthalten, ändere ich meine Abfrage in:
In dieser Abfrage kann SQL die CustomerID aus dem nicht gruppierten Index lesen. Der Clustered-Index muss nicht durchsucht werden. Dies können Sie dem Ausführungsplan entnehmen, der so aussieht.
Beachten Sie den Unterschied zwischen dieser Abfrage und der vorherigen Abfrage. Es gibt keine Suche. SQL kann alle Daten im nicht gruppierten Index finden
Hoffentlich können Sie anfangen zu verstehen, dass der Clustered-Index die Tabelle ist und Nicht-Clustered-Indizes NICHT alle Daten enthalten. Die Indizierung beschleunigt die Auswahl, da binäre Suchen durchgeführt werden können, aber nur Clustered-Indizes alle Daten enthalten. Daher führt eine Suche in einem nicht gruppierten Index fast immer dazu, dass Werte aus dem gruppierten Index geladen werden. Diese zusätzlichen Vorgänge führen dazu, dass nicht gruppierte Indizes weniger effizient sind als ein gruppierter Index.
Hoffe das klärt die Dinge auf. Wenn irgendetwas keinen Sinn ergibt, schreibe bitte einen Kommentar und ich versuche es zu klären. Es ist ziemlich spät hier und mein Gehirn fühlt sich ein bisschen platt. Zeit für einen roten Bullen.
quelle
"Dies bedeutet, dass die Abfrage-Engine einen zusätzlichen Schritt ausführen muss, um die tatsächlichen Daten zu lokalisieren."
Nicht unbedingt - wenn der Index eine bestimmte Abfrage abdeckt, muss kein Trip zu den Datenseiten durchgeführt werden. Mit eingeschlossenen Spalten können auch zusätzliche Spalten zu einem nicht gruppierten Index hinzugefügt werden, damit dieser abgedeckt wird, ohne die Schlüsselgröße zu ändern.
Die endgültige Antwort lautet also: - Es kommt darauf an (dass Sie viel mehr Informationen benötigen, als Sie wirklich in einer einzigen Frage behandeln können) - Sie müssen alle Funktionen der Indizes verstehen, und der Ausführungsplan für eine bestimmte Abfrage kann von Ihren Erwartungen abweichen.
Eine allgemeine Faustregel ist, dass eine Tabelle immer einen Clustered-Index (und normalerweise eine Identität oder eine sequenzielle GUID) hat, aber nicht-Clustered-Indizes werden zur Verbesserung der Leistung hinzugefügt. Es gibt jedoch immer Ausnahmen - Heap-Tabellen haben einen Platz, breitere Clustered-Indizes haben einen Platz. Scheinbar redundante Indizes, die schmaler sind, um mehr Zeilen pro Seite aufzunehmen, haben einen Platz. usw. usw.
Und ich würde mir keine Sorgen um die Beschränkungen der verschiedenen zulässigen Indizes machen - das wird in vielen Beispielen aus der Praxis mit ziemlicher Sicherheit nicht zum Tragen kommen.
quelle
there are always exceptions
- zu viele Leute lassen dies aus und denken, dass jeder Clustered-Index einint identity
egal was sein sollte.