it-swarm.com.de

Clustered vs Non-Clustered

Meine Grundkenntnisse in SQL (Server 2008) sind begrenzt und werden jetzt von unseren Datenbankadministratoren geändert. Lassen Sie mich das Szenario erklären (ich habe offensichtliche Aussagen in der Hoffnung erwähnt, dass ich Recht habe, aber wenn Sie etwas falsch sehen, sagen Sie es mir bitte):

Wir haben einen Tisch, der 'Gerichtsbeschlüsse' für Menschen enthält. Als ich die Tabelle (Name: CourtOrder) erstellt habe, habe ich sie folgendermaßen erstellt:

CREATE TABLE dbo.CourtOrder
(
  CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
  PersonId INT NOT NULL,
  + around 20 other fields of different types.
)

Ich habe dann einen nicht gruppierten Index auf den Primärschlüssel angewendet (aus Effizienzgründen). Meine Gründe sind, dass es sich um ein eindeutiges Feld (Primärschlüssel) handelt, das hauptsächlich zu Auswahlzwecken indiziert werden sollte, da wir häufig Select from table where primary key = ...

Ich habe dann einen CLUSTERED-Index auf PersonId angewendet. Der Grund war, Aufträge für eine bestimmte Person physisch zu gruppieren, da die überwiegende Mehrheit der Arbeit Aufträge für eine Person erhält. Also, select from mytable where personId = ...

Ich bin jetzt darüber aufgeklärt worden. Mir wurde gesagt, dass wir den gruppierten Index auf den Primärschlüssel und den normalen Index auf die personId setzen sollen. Das kommt mir sehr merkwürdig vor. Warum sollten Sie zunächst einen Clustered-Index für eine eindeutige Spalte erstellen? Was ist Clustering? Sicherlich ist das eine Verschwendung des Clustered-Index? Ich hätte geglaubt, ein normaler Index würde für eine eindeutige Spalte verwendet. Außerdem würde das Clustering des Index bedeuten, dass keine andere Spalte geclustert werden kann (eine pro Tabelle, oder?).

Der Grund, warum mir gesagt wurde, dass ich einen Fehler gemacht habe, ist, dass sie glauben, ein Clustered-Index für die PersonId würde die Einfügungen verlangsamen. Bei einem Geschwindigkeitsgewinn von 5% bei ausgewählten Elementen und Aktualisierungen würde sich die Geschwindigkeit um 95% verschlechtern. Ist das richtig und gültig?

Sie sagen, da wir die personId gruppieren, muss SQL Server die Daten jedes Mal neu anordnen, wenn wir die personId einfügen oder ändern.

Also habe ich gefragt, warum SQL das Konzept eines CLUSTERED INDEX hat, wenn es so langsam ist? Ist es so langsam wie sie sagen? Wie sollte ich meine Indizes einrichten, um eine optimale Leistung zu erzielen? Ich hätte gedacht, SELECT wird mehr als INSERT verwendet ... aber es wird gesagt, dass wir Probleme beim Sperren von INSERTS haben ...

Hoffe mir kann jemand helfen.

95
Craig

Der Unterschied zwischen einem gruppierten und einem nicht gruppierten Index besteht darin, dass der gruppierte Index bestimmt die physische Reihenfolge der Zeilen in der Datenbank. Mit anderen Worten, das Anwenden des gruppierten Index auf PersonId bedeutet, dass die Zeilen physisch nach PersonId in der Tabelle sortiert werden, sodass eine Indexsuche direkt zu der Zeile (statt zu a) führt nicht gruppierter Index, der Sie zum Speicherort der Zeile weiterleitet und einen zusätzlichen Schritt hinzufügt).

Das heißt, es ist ngewöhnlich, dass der Primärschlüssel nicht der Clustered-Index ist, aber nicht unbekannt. Das Problem mit Ihrem Szenario ist eigentlich das Gegenteil von dem, was Sie annehmen: Sie möchten eindeutige Werte in einem Clustered-Index, keine Duplikate. Da der Clustered-Index die physische Reihenfolge der Zeile bestimmt, muss der Server Zeilen, die einen doppelten Schlüsselwert aufweisen, einen Hintergrundwert hinzufügen, wenn sich der Index in einer nicht eindeutigen Spalte befindet (in Ihrem Fall alle Zeilen mit demselben Schlüsselwert) PersonId), so dass der kombinierte Wert (Schlüssel + Hintergrundwert) eindeutig ist.

Das einzige, was ich vorschlagen würde, ist nicht Verwenden eines Ersatzschlüssels (Ihrer CourtOrderId) als Primärschlüssel, aber verwenden Sie stattdessen einen zusammengesetzten Primärschlüssel des PersonId und eine andere eindeutig identifizierende Spalte oder Gruppe von Spalten. Wenn dies jedoch nicht möglich (oder nicht praktikabel) ist, setzen Sie den Clustered-Index auf CourtOrderId.

115
Adam Robinson

Ich bin auf keinen Fall ein SQL-Experte. Nehmen Sie dies als Entwicklersicht und nicht als DBA-Sicht.

Einfügungen in gruppierten (physisch geordneten) Indizes, die nicht in sequenzieller Reihenfolge vorliegen, verursachen zusätzlichen Aufwand für Einfügungen/Aktualisierungen. Wenn viele Einfügungen gleichzeitig und alle an derselben Stelle vorkommen, kommt es zu Konflikten. Ihre spezifische Leistung hängt von Ihren Daten und davon ab, wie Sie darauf zugreifen. Die allgemeine Faustregel besteht darin, den Clustered-Index auf der Grundlage des eindeutigsten engen Werts in Ihrer Tabelle (normalerweise der PK) zu erstellen.

Ich gehe davon aus, dass sich Ihre PersonId nicht ändert, sodass hier keine Updates zum Tragen kommen. Betrachten Sie jedoch einen Schnappschuss einiger Zeilen mit der PersonId 1 2 3 3 4 5 6 7 8 8

Fügen Sie nun 20 neue Zeilen für PersonId von 3 ein. Da dies kein eindeutiger Schlüssel ist, fügt der Server Ihrem Wert (hinter den Kulissen) einige zusätzliche Bytes hinzu, um ihn eindeutig zu machen (wodurch auch zusätzlicher Speicherplatz hinzugefügt wird) und anschließend den Speicherort diese müssen geändert werden. Vergleichen Sie dies mit dem Einfügen einer automatisch inkrementierenden PK, bei der die Einfügungen am Ende erfolgen. Die nicht-technische Erklärung würde wahrscheinlich so aussehen: Es ist weniger "Blättern mischen" zu tun, wenn die Werte am Ende der Tabelle naturgemäß höher sind, als die Position der vorhandenen Elemente an dieser Position beim Einfügen der Elemente zu überarbeiten.

Wenn Sie nun Probleme mit Einfügungen haben, fügen Sie wahrscheinlich eine Reihe derselben (oder ähnlicher) PersonId-Werte gleichzeitig ein, was diese zusätzliche Arbeit an verschiedenen Stellen in der Tabelle verursacht, und die Fragmentierung bringt Sie um. Der Nachteil des Wechsels zu der zu gruppierenden PK besteht in Ihrem Fall darin, dass Sie heute Einfügeprobleme bei Personen-IDs haben, deren Wert über die Tabelle verteilt ist, wenn Sie Ihren gruppierten Index zur PK wechseln und alle Einfügungen jetzt in einer erfolgen In diesem Fall kann sich das Problem aufgrund der erhöhten Konfliktkonzentration tatsächlich verschlechtern. (Auf der anderen Seite wird Ihr Problem wahrscheinlich dadurch gelöst, dass Sie den gruppierten Index von PersonId auf Ihre PK umstellen, da Sie die Anzahl der Einfügungen minimieren, wenn Ihre heutigen Einfügungen nicht überall verteilt sind, sondern in der Regel alle in ähnlichen Bereichen gebündelt sind Zersplitterung.)

Ihre Leistungsprobleme sollten auf Ihre individuelle Situation hin analysiert werden und diese Art von Antworten nur als allgemeine Richtlinien verwenden. Am besten verlassen Sie sich auf einen DBA, der genau überprüft, wo Ihre Probleme liegen. Es hört sich so an, als hätten Sie Probleme mit Ressourcenkonflikten, die möglicherweise über einen einfachen Index-Tweak hinausgehen. Dies könnte ein Symptom für ein viel größeres Problem sein. (Wahrscheinliche Designprobleme ... ansonsten Ressourcenbeschränkungen.)

Auf jeden Fall viel Glück!

13
Darian Miller

Einige Autoren raten davon ab, CI in einer identity -Spalte zu "verschwenden", wenn es eine Alternative gibt, von der Bereichsabfragen profitieren würden.

Aus MSDN Clustered Index Design Guidelines sollte der Schlüssel gemäß den folgenden Kriterien ausgewählt werden

  1. Kann für häufig verwendete Abfragen verwendet werden.
  2. Sorgen Sie für ein hohes Maß an Einzigartigkeit.
  3. Kann in Bereichsabfragen verwendet werden.

Ihre CourtOrderID Spalte entspricht 2. Ihr PersonId erfüllt 1 Und 3. Da die meisten Zeilen ohnehin mit dem uniqueifier versehen werden, können Sie es genauso gut als eindeutig deklarieren und PersonId,CourtOrderID Verwenden, da dies die gleiche Breite hat, aber nützlicher ist als der gruppierte Indexschlüssel wird allen NCIs als Zeilenlokator hinzugefügt, sodass sie mehr Abfragen abdecken können.

Das Hauptproblem bei der Verwendung von PersonId,CourtOrderID Als CI besteht darin, dass wahrscheinlich eine logische Fragmentierung auftritt (und dies wirkt sich insbesondere auf die Bereichsabfragen aus, bei denen Sie helfen möchten), sodass Sie den Füllfaktor und die Fragmentierungsstufen überwachen und einen Index durchführen müssen Wartung öfter.

5
Martin Smith

Es wird unter folgendem Link erklärt: https://msdn.Microsoft.com/en-us/ms190457.aspx

Clustered

  • Clustered-Indizes sortieren und speichern Sie die Datenzeilen in der Tabelle oder Ansicht basierend auf ihren Schlüsselwerten. Dies sind die Spalten, die in der Indexdefinition enthalten sind. Es kann nur einen Clustered-Index pro Tabelle geben, da die Datenzeilen selbst nur in einer Reihenfolge sortiert werden können.

  • Die Datenzeilen in einer Tabelle werden nur dann in sortierter Reihenfolge gespeichert, wenn die Tabelle einen Clustered-Index enthält. Wenn eine Tabelle einen Clustered-Index hat, wird die Tabelle als Clustered-Tabelle bezeichnet. Wenn eine Tabelle keinen Clustered-Index hat, werden ihre Datenzeilen in einer ungeordneten Struktur gespeichert, die als Heap bezeichnet wird.

Nonclustered

  • Nonclustered-Indizes haben eine von den Datenzeilen getrennte Struktur. Ein nicht gruppierter Index c erhält die nicht gruppierten Indexschlüsselwerte und jeder Schlüsselwerteintrag hat einen Zeiger auf die Datenzeile, die den Schlüsselwert enthält.

  • Der Zeiger von einer Indexzeile in einem nicht gruppierten Index auf eine Datenzeile wird als Zeilenlokalisierer bezeichnet. Die Struktur des Zeilenfinders hängt davon ab, ob die Datenseiten in einem Heap oder in einer Clustertabelle gespeichert sind. Bei einem Heap ist ein Zeilenlokator ein Zeiger auf die Zeile. Bei einer gruppierten Tabelle ist der Zeilenlokator der gruppierte Indexschlüssel.

  • Sie können der Blattebene des nicht gruppierten Index Nichtschlüsselspalten hinzufügen, um vorhandene Indexschlüsselgrenzwerte (900 Byte und 16 Schlüsselspalten) zu umgehen und vollständig abgedeckte, indizierte Abfragen auszuführen.

3
user2191454