Meine SQL-Kenntnisse auf niedrigerer Ebene (Server 2008) sind begrenzt und werden jetzt von unseren Datenbankadministratoren gefordert. 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 wie folgt 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 und wie häufig indiziert werden sollte, hauptsächlich zu AuswahlzweckenSelect from table where primary key = ...
Ich habe dann einen CLUSTERED-Index auf PersonId angewendet. Der Grund war, Bestellungen für eine bestimmte Person physisch zu gruppieren, da die überwiegende Mehrheit der Arbeit darin besteht, Bestellungen für eine Person zu erhalten. So,select from mytable where personId = ...
Ich bin jetzt darüber aufgezogen worden. Mir wurde gesagt, dass wir den Clustered-Index auf den Primärschlüssel und den normalen Index auf die personId setzen sollen. Das kommt mir sehr seltsam vor. Warum sollten Sie zunächst einen Clustered-Index für eine eindeutige Spalte erstellen? Was ist es Clustering? Sicher ist das eine Verschwendung des Clustered-Index? Ich hätte geglaubt, dass ein normaler Index für eine eindeutige Spalte verwendet wird. Das Clustering des Index würde auch bedeuten, dass wir keine andere Spalte gruppieren können (eine pro Tabelle, richtig?).
Der Grund dafür, dass mir mitgeteilt wurde, dass ich einen Fehler gemacht habe, ist, dass sie glauben, dass das Einfügen eines Clustered-Index in die PersonId das Einfügen verlangsamen würde. Für den Geschwindigkeitszuwachs von 5% einer Auswahl würden wir eine 95% ige Geschwindigkeitsverschlechterung bei Einfügungen und Aktualisierungen erhalten. Ist das richtig und gültig?
Sie sagen, dass SQL Server, da wir die personId gruppieren, Daten neu anordnen muss, wenn wir die PersonId einfügen oder ändern.
Dann habe ich gefragt, warum SQL das Konzept eines CLUSTERED INDEX haben sollte, 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, dass SELECT mehr als INSERT verwendet wird ... aber sie sagen, dass wir Probleme beim Sperren von INSERTS haben ...
Hoffe jemand kann mir helfen.
Antworten:
Der Unterschied zwischen einem Clustered-Index und einem Nicht-Clustered-Index besteht darin, dass der Clustered-Index die physische Reihenfolge der Zeilen in der Datenbank bestimmt . Mit anderen Worten
PersonId
bedeutet das Anwenden des Clustered-Index auf , dass die ZeilenPersonId
in der Tabelle physisch sortiert werden , sodass eine Indexsuche in dieser Zeile direkt zur Zeile führt (und nicht zu einem nicht gruppierten Index, der Sie zu den Zeilen führt Ort, einen zusätzlichen Schritt hinzufügen).Es ist jedoch ungewö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 mit einem doppelten Schlüsselwert (in Ihrem Fall alle Zeilen mit demselben) einen Hintergrundwert hinzufügen, wenn sich der Index in einer nicht eindeutigen Spalte befindet
PersonId
), so dass der kombinierte Wert (Schlüssel + Hintergrundwert) eindeutig ist.Das einzige, was ich vorschlagen würde, ist, nicht einen Ersatzschlüssel (Ihre
CourtOrderId
) als Primärschlüssel zu verwenden, sondern einen zusammengesetzten Primärschlüssel derPersonId
und einer anderen eindeutig identifizierenden Spalte oder eines Satzes von Spalten. Wenn dies jedoch nicht möglich (oder nicht praktikabel) ist, setzen Sie den Clustered-Index aufCourtOrderId
.quelle
PersonId
. Es ist logisch sortiert nachPersonId
, jede Diskrepanz zwischen logischer und physischer Reihenfolge ist der Grad der logischen Fragmentierung.Ich bin auf keinen Fall ein SQL-Experte. Nehmen Sie dies also eher als Entwickleransicht als als DBA-Ansicht.
Einfügungen in gruppierten (physisch geordneten) Indizes, die nicht in sequentieller Reihenfolge vorliegen, verursachen zusätzliche Arbeit für Einfügungen / Aktualisierungen. Wenn mehrere Einfügungen gleichzeitig ausgeführt werden und alle am selben Ort ausgeführt werden, kommt es zu Konflikten. Ihre spezifische Leistung hängt von Ihren Daten und dem Zugriff darauf ab. Die allgemeine Faustregel lautet, dass Sie Ihren Clustered-Index auf dem eindeutigsten schmalen Wert in Ihrer Tabelle (normalerweise der PK) erstellen.
Ich gehe davon aus, dass sich Ihre PersonId nicht ändert, sodass hier keine Updates ins Spiel 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 dann den Ort, an dem Diese werden sich ändern müssen. 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 darauf zurückzuführen sein: Es ist weniger Arbeit zum Mischen von Blättern erforderlich, wenn am Ende der Tabelle auf natürliche Weise höhere Werte erreicht werden als beim Einfügen Ihrer Elemente die Position der vorhandenen Elemente an dieser Position überarbeitet wird.
Wenn Sie 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 Sie umbringt. Der Nachteil des Wechsels zu der PK, die in Ihrem Fall geclustert wird, besteht darin, dass Sie heute Einfügeprobleme bei PersonIds haben, deren Wert in der Tabelle verteilt ist, wenn Sie Ihren Clustered-Index auf die PK umstellen und alle Einfügungen jetzt in einer erfolgen Ort, dann kann sich Ihr Problem aufgrund der erhöhten Konfliktkonzentration tatsächlich verschlimmern. (Auf der anderen Seite wird Ihr Problem wahrscheinlich behoben, wenn Ihre Einfügungen heute nicht über alle Bereiche verteilt sind, sondern in der Regel in ähnlichen Bereichen zusammengefasst sind, indem Sie Ihren Clustered-Index von PersonId auf Ihre PK umstellen, da Sie die Anzahl der Einfügungen minimieren 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 über eine einfache Indexoptimierung hinausgehen könnten. Dies könnte ein Symptom für ein viel größeres Problem sein. (Wahrscheinlich Designprobleme ... sonst Ressourcenbeschränkungen.)
Auf jeden Fall viel Glück!
quelle
Einige Autoren schlagen nicht die „verschwenden“
CI
auf eineridentity
Säule , wenn es eine Alternative , die Bereichsabfragen profitieren würde.Aus den MSDN Clustered Index Design Guidelines sollte der Schlüssel gemäß den folgenden Kriterien ausgewählt werden
Ihre
CourtOrderID
Kolumne trifft sich2
. IhrePersonId
Treffen1
und3
. Da die meisten Zeilenuniqueifier
ohnehin hinzugefügt werden, können Sie es genauso gut als eindeutig deklarieren und verwenden,PersonId,CourtOrderID
da dies dieselbe Breite hat, aber nützlicher ist, da der Clustered-Indexschlüssel allen NCIs als Zeilenlokator hinzugefügt wird und dies ermöglicht sie, um mehr Fragen zu decken.Das Hauptproblem bei der Verwendung
PersonId,CourtOrderID
als CI besteht darin, dass wahrscheinlich eine logische Fragmentierung auftritt (und dies wirkt sich insbesondere auf die Bereichsabfragen aus, denen Sie helfen möchten), sodass Sie den Füllfaktor und die Fragmentierungsstufen überwachen und die Indexwartung häufiger durchführen müssen.quelle
Dies wird unter folgendem Link erläutert: https://msdn.microsoft.com/en-us/ms190457.aspx
Clustered
Clustered-Indizes sortieren und speichern 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.
Nicht gruppiert
Nicht gruppierte Indizes haben eine von den Datenzeilen getrennte Struktur. Ein nicht gruppierter Index enthält die nicht gruppierten Indexschlüsselwerte, und jeder Schlüsselwerteintrag verfügt über 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 Zeilenlokator bezeichnet. Die Struktur des Zeilenlokators hängt davon ab, ob die Datenseiten in einem Heap oder einer Clustertabelle gespeichert sind. Bei einem Heap ist ein Zeilenlokator ein Zeiger auf die Zeile. Bei einer Clustertabelle ist der Zeilenlokator der Clustered-Indexschlüssel.
Sie können der Blattebene des nicht gruppierten Index Spalten ohne Schlüssel hinzufügen, um vorhandene Indexschlüsselgrenzen, 900 Byte und 16 Schlüsselspalten zu umgehen und vollständig abgedeckte, indizierte Abfragen auszuführen.
quelle
Einige Datenbanken mit einigen bösen Auswahlen schließen sich einer gespeicherten Prozedur an - nur der Unterschied ist der Index
INDEXE - gruppiert gegen nicht gruppiert
quelle