Müssen Clustered-Indizes eindeutig sein?

83

Was passiert, wenn ein Clustered-Index nicht eindeutig ist? Kann dies zu einer schlechten Leistung führen, da eingefügte Zeilen zu einer Art "Überlauf" -Seite fließen?

Ist es einzigartig "gemacht" und wenn ja wie? Was ist der beste Weg, um es einzigartig zu machen?

Ich frage, weil ich derzeit einen Clustered-Index verwende, um meine Tabelle in logische Teile zu unterteilen, aber die Leistung ist mittelmäßig, und kürzlich habe ich den Rat erhalten , meine Clustered-Indizes eindeutig zu machen. Ich hätte gerne eine zweite Meinung dazu.

Vielen Dank!

Littlegreen
quelle

Antworten:

90

Sie haben nicht haben , einzigartig zu sein , aber es wird sicherlich dazu ermutigt.
Ich habe noch kein Szenario gefunden, in dem ich ein CI für eine nicht eindeutige Spalte erstellen wollte.

Was passiert, wenn Sie ein CI für eine nicht eindeutige Spalte erstellen ?

Wenn der Clustered-Index kein eindeutiger Index ist, macht SQL Server alle doppelten Schlüssel eindeutig, indem ein intern generierter Wert hinzugefügt wird, der als Uniqueifier bezeichnet wird

Führt dies zu einer schlechten Leistung?

Das Hinzufügen eines Uniqueifizierers erhöht sicherlich den Aufwand beim Berechnen und Speichern.
Ob sich dieser Aufwand bemerkbar macht, hängt von mehreren Faktoren ab.

  • Wie viele Daten enthält die Tabelle?
  • Wie hoch ist die Anzahl der Einsätze?
  • Wie oft wird das CI in einer Auswahl verwendet (wenn keine abdeckenden Indizes vorhanden sind, so ziemlich immer).

Bearbeiten
wie durch Remus in Kommentaren darauf hingewiesen, es existieren Anwendungsfälle , wo eine nicht eindeutige CI Schaffung eine vernünftige Wahl sein würde. Wenn ich nicht auf eines dieser Szenarien gestoßen bin, zeigt dies lediglich meinen eigenen Mangel an Belichtung oder Kompetenz (wählen Sie Ihre Wahl).

Lieven Keersmaekers
quelle
30
+1, weil alles, was Sie sagen, korrekt ist, aber nur hinzufügen wollte: Nicht eindeutige CI sind recht häufig, wenn Bereichsscans für eine bestimmte (nicht eindeutige) Spalte das vorherrschende Zugriffsmuster sind.
Remus Rusanu
@Remus Rusanu: Ich habe darüber nachgedacht, meiner Szenario-Aussage einen Haftungsausschluss hinzuzufügen, aber das hat nichts zu bedeuten . Vielen Dank, dass Sie auf ein Szenario hingewiesen haben, in dem es nützlich sein könnte.
Lieven Keersmaekers
4
@Remus: Du meinst also die Nischensituation, in der du eine nicht eindeutige Spalte wie 'Departmentid' hast, in der du etwas wie 'DepartmentId ZWISCHEN 1 und 100' abfragst? edit ah ich verstehe was du meinst, ja eine datumsspalte in einer protokollierungstabelle ist auch ein gutes beispiel.
Littlegreen
Hey, ich habe eine Ereignisstromtabelle, in der mehrere Zeilen mit derselben "AggregateId" existieren, die eine Spalte für den Typ GUID ist. Die einzigen Abfragen, die für die Tabelle ausgeführt werden, bestehen darin, alle Ereignisse für eine bestimmte AggregateId abzurufen. Ich frage mich, ob dies ein Clustered-Index oder ein Nicht-Clustered-Index sein soll.
Shayan C
@ShayanC - Wenn die Leistung des Abrufs Ihr primäres Ziel ist, würde ich es zu einem CI machen, um beim Abrufen aller Zeilen für eine bestimmte ID wahrscheinlich E / A zu sparen. Wie bei allen Leistungsszenarien ist die Messung jedoch nur sicher.
Lieven Keersmaekers
31

Ich möchte herausfinden, was die Königin der Indexierung, Kimberly Tripp, zu diesem Thema zu sagen hat:

Ich werde mit meiner Empfehlung für den Clustering-Schlüssel beginnen - aus mehreren Gründen. Erstens ist es eine einfache Entscheidung, und zweitens hilft eine frühzeitige Entscheidung, einige Arten der Fragmentierung proaktiv zu verhindern. Wenn Sie bestimmte Arten der Fragmentierung von Basistabellen verhindern können, können Sie einige Wartungsaktivitäten minimieren (von denen einige in SQL Server 2000 und weniger in SQL Server 2005 erfordern, dass Ihre Tabelle offline ist. OK, ich komme später zum Wiederaufbau .....

Beginnen wir mit den wichtigsten Dingen, nach denen ich in einem Clustering-Schlüssel suche:

* Unique
* Narrow
* Static

Warum einzigartig? Ein Clustering-Schlüssel sollte eindeutig sein, da ein Clustering-Schlüssel (sofern vorhanden) als Suchschlüssel für alle nicht geclusterten Indizes verwendet wird. Nehmen Sie zum Beispiel einen Index am Ende eines Buches. Wenn Sie die Daten suchen müssen, auf die ein Indexeintrag verweist, muss dieser Eintrag (der Indexeintrag) andernfalls eindeutig sein. Welcher Indexeintrag ist derjenige, nach dem Sie suchen ? Wenn Sie also den Clustered-Index erstellen, muss er eindeutig sein. Für SQL Server ist es jedoch nicht erforderlich, dass Ihr Clustering-Schlüssel in einer eindeutigen Spalte erstellt wird. Sie können es für jede gewünschte Spalte erstellen. Wenn der Clustering-Schlüssel intern nicht eindeutig ist, wird er von SQL Server durch Hinzufügen einer 4-Byte-Ganzzahl zu den Daten "eindeutig". Wenn der Clustered-Index für etwas erstellt wird, das nicht eindeutig ist, entsteht bei der Indexerstellung nicht nur zusätzlicher Aufwand, sondern auch Speicherplatz.

Quelle: Immer mehr Clustering-Schlüsseldebatte - wieder!

marc_s
quelle
Eine Frage, die Queen empfiehlt eine neue Sequenz-ID, um die Daten zu eindeutig zu machen, aber SQL Server generiert einen eigenen Eindeutiger, wenn Sie ihn nicht angeben. Gibt es dann noch einen Grund, eine eigene sequenzielle ID hinzuzufügen?
littlegreen
2
@littlegreen: Sie sagt, wenn Sie darauf bestehen, GUIDs zu verwenden (die für die Verwendung in einem Clustering-Index wirklich sehr, sehr schlecht sind), dann verwenden Sie zumindest newsequentialid(), um eine fast sequenzielle GUID zu erhalten. Aber ja: Wenn Sie Ihre eigene eindeutige ID hinzufügen (ich bevorzuge immer INT IDENTITY), haben Sie diesen Wert zur Hand und können ihn verwenden (z. B. um eine FK-Beziehung aufzubauen). Die von SQL Server hinzugefügten Uniquefiers sind für Sie unsichtbar und daher nur Overhead, den Sie nicht nutzen können.
marc_s
Aha. Nun, das wäre ein Argument für einen Clustered-Index (CompanyID, DepartmentID, id INT IDENTITY) anstelle der ersten beiden. Vielen Dank!
littlegreen
1
@littlegreen: Besser noch - machen Sie Ihren Clustered-Index nur auf (ID INT IDENTITY) und fügen Sie die anderen Felder - falls erforderlich - in einen separaten, nicht gruppierten Index ein. Der Clustered-Index sollte so klein wie möglich sein. Schließlich werden die Clustered-Indexspalten auch zu jedem Eintrag jedes einzelnen nicht-Clustered-Index in dieser Tabelle hinzugefügt. Verschwenden Sie Ihre Bytes also nicht mit einem breiten Cluster Index!
marc_s
1
Ja, aber dann verliere ich den Vorteil, dass alle meine Abteilungsdaten gruppiert werden und ich in der Lage bin, eine ganze Abteilung auf einmal einzufügen / zu löschen / abzurufen. Meine Daten werden verstreut und Einfügungen / Löschungen in ganzen Abteilungen oder sogar ganzen Unternehmen werden langsam sein. Meine Abfragen werden immer nur von einem Unternehmen gleichzeitig ausgeführt, und häufig muss ein ganzer Datensatz aktualisiert werden.
littlegreen
9

Müssen Clustered-Indizes eindeutig sein?

Sie tun es nicht und es gibt Zeiten, in denen es besser ist, wenn sie es nicht sind.

Stellen Sie sich eine Tabelle mit einer halbzufälligen, eindeutigen Mitarbeiter-ID und einer Abteilungs-ID für jeden Mitarbeiter vor: Wenn Ihre select-Anweisung lautet

SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%

Dann ist es am besten für die Leistung, wenn DepartmentIdes sich um den Clustered-Index handelt, obwohl (oder sogar besonders, weil) es sich nicht um den eindeutigen Index handelt (am besten für die Leistung, da sichergestellt wird, dass alle Datensätze innerhalb einer bestimmten DepartmentId geclustert werden).


Haben Sie Referenzen?

Es gibt zum Beispiel Richtlinien für das Design von Clustered - Indizes , die besagen:

Mit wenigen Ausnahmen sollte für jede Tabelle ein Clustered-Index für die Spalte (n) definiert sein, die Folgendes bieten:

  • Kann für häufig verwendete Abfragen verwendet werden.
  • Bieten Sie ein hohes Maß an Einzigartigkeit.
  • Kann in Bereichsabfragen verwendet werden.

Mein Verständnis von "hohem Grad an Einzigartigkeit" ist beispielsweise, dass es nicht gut ist, "Land" als überfüllten Index zu wählen, wenn die meisten Ihrer Abfragen die Datensätze innerhalb einer bestimmten Stadt auswählen möchten.

ChrisW
quelle
Ja, das habe ich mir bis jetzt gedacht, aber ich bekomme auch genau den gegenteiligen Rat, also frage ich mich, was wahr ist. Haben Sie Referenzen?
littlegreen
@littlegreen Ich habe meine Antwort bearbeitet, um zu versuchen, Ihre Frage zu beantworten.
ChrisW
Vielen Dank. Ja, okay, ich verstehe deinen Standpunkt. Wenn Sie jedoch regelmäßig ein ganzes Land auf einmal einfügen, erscheint mir ein Clustered-Index für (Land, Stadt) umständlich, da die Daten sortiert werden müssen. Auf der anderen Seite wäre eine Sortierung vor dem Einfügen nicht so
schwierig
3
Sicherlich wäre in Ihrem Beispiel ein eindeutiger Clustered-Index für {DepartmentID, EmployeeID} vorzuziehen? Warum hat das System einen eindeutigen Bezeichner erstellt, wenn Ihr vorhandenes Feld eine Eindeutigkeit mit weniger Overhead (wahrscheinlich eine 4-Byte-INT) bietet und Sie möglicherweise allein im Index einige weitere Abfragen ausführen können?