Uniqueneidentifier vs. IDENTITY vs. Material Code - was ist die beste Wahl für Primärschlüssel?

8

Welches ist die beste Wahl für den Primärschlüssel in SQL Server?
Es gibt einen Beispielcode:

Uniqueneidentifier

z. B.

%Vor%

Identitätsspalten

z. B.

%Vor%

[Materialcode] (oder Geschäftscode, welche Identität eines Materials, z. B. Kunden-ID)

z. B.

%Vor%

Bitte geben Sie mir einige Tipps, wie Sie den Primärschlüssel aus den drei Spalten für die Typidentität oder anderen Optionen auswählen können.

Danke!

    
huoxudong125 09.12.2013, 05:31
quelle

4 Antworten

14

GUID scheint eine natürliche Wahl für Ihren Primärschlüssel zu sein - und wenn Sie wirklich müssen, könnten Sie wahrscheinlich argumentieren, sie für den PRIMÄRSCHLÜSSEL der Tabelle zu verwenden. Ich empfehle nicht , dass Sie die Spalte GUID als Clustering-Schlüssel verwenden, was SQL Server standardmäßig tut, es sei denn, Sie sagen es ausdrücklich nicht.

Sie müssen wirklich zwei Ausgaben auseinander halten:

  1. Der Primärschlüssel ist ein logisches Konstrukt - einer der Kandidatenschlüssel, der jede Zeile in Ihrer Tabelle eindeutig und zuverlässig identifiziert. Dies kann alles sein, wirklich - ein INT , ein GUID , ein String - wählen Sie, was am sinnvollsten für Ihr Szenario ist.

  2. der Clustering-Schlüssel (die Spalte oder die Spalten, die den "Clustered-Index" in der Tabelle definieren) - dies ist eine physische speicherbezogene Sache, und Hier ist ein kleiner, stabiler, ständig wachsender Datentyp die beste Wahl - INT oder BIGINT als Standardoption.

Standardmäßig wird der Primärschlüssel in einer SQL Server-Tabelle auch als Clustering-Schlüssel verwendet - das muss aber nicht so sein! Ich habe persönlich massive Leistungssteigerungen erlebt, als ich den vorherigen GUID-basierten Primär / Clustered-Schlüssel in zwei separate Schlüssel aufteilte - den primären (logischen) Schlüssel in GUID und den Clustering- (Bestell-) Schlüssel in einem separaten INT IDENTITY(1,1) Säule.

Als Kimberly Tripp - Die Königin der Indexierung - und andere haben sehr oft angegeben - a GUID als Clustering-Schlüssel ist nicht optimal, da es aufgrund seiner Zufälligkeit zu einer massiven Fragmentierung von Seiten und Indizes führt und generell schlechte Leistung.

Ja, ich weiß - es gibt newsequentialid() in SQL Server 2005 und höher - aber selbst das ist nicht wirklich und vollständig sequenziell und leidet daher auch unter den gleichen Problemen wie GUID - nur etwas weniger prominent.

Dann gibt es noch ein weiteres Problem: Der Clustering-Schlüssel einer Tabelle wird zu jedem Eintrag in jedem einzelnen nicht gruppierten Index auf Ihrer Tabelle hinzugefügt. Sie möchten also sicherstellen, dass er so klein wie möglich ist . Normalerweise sollte ein INT mit 2+ Milliarden Zeilen für die überwiegende Mehrheit der Tabellen ausreichen - und im Vergleich zu einem GUID als Clustering-Schlüssel können Sie Hunderte von Megabyte Speicherplatz auf der Festplatte und im Serverspeicher sparen.

Schnelle Berechnung - mit INT vs. GUID als primärer Schlüssel und Clustering-Schlüssel:

  • Basistabelle mit 1'000'000 Zeilen (3,8 MB vs. 15,26 MB)
  • 6 Nonclustered-Indizes (22,89 MB vs. 91,55 MB)

GESAMT: 25 MB vs. 106 MB - und das nur auf einem einzigen Tisch!

Etwas mehr zum Nachdenken - hervorragende Sachen von Kimberly Tripp - lesen Sie es, lesen Sie es noch einmal, verdauen Sie es! Es ist die SQL Server-Indizierung Gospel, wirklich.

Wenn Sie keinen sehr guten Grund haben, würde ich argumentieren, dass INT IDENTITY für fast jede "echte" Datentabelle als Standard für ihren Primärschlüssel verwendet wird - sie ist einzigartig, sie ist stabil (nie Änderungen), es ist eng, es wird immer größer - all die guten Eigenschaften , die Sie in einem Clusterschlüssel für die schnelle und zuverlässige Leistung Ihrer SQL Server-Tabellen haben möchten!

Wenn Sie einen "natürlichen" Schlüsselwert haben, der auch alle diese Eigenschaften hat, können Sie diesen Schlüssel auch anstelle eines Ersatzschlüssels verwenden. Aber zwei Strings mit variabler Länge von max. 20 Zeichen erfüllen diese Anforderungen meiner Meinung nach nicht.

    
marc_s 09.12.2013, 05:38
quelle
4

IDENTITÄT

PROS

  1. kleiner Speicherbedarf;
  2. optimale Join / Index-Leistung (z. B. bei Zeitbereichsabfragen liegen die zuletzt eingefügten Zeilen auf einer begrenzten Anzahl von Seiten);
  3. sehr nützlich für Data Warehousing;
  4. nativer Datentyp des Betriebssystems und einfach in allen Sprachen zu arbeiten;
  5. leicht zu debuggen;
  6. automatisch generiert (abgerufen über SCOPE_IDENTITY () anstatt zugewiesen);
  7. nicht updatebar (obwohl einige dies seltsamerweise seltsamerweise für einen Nachteil halten).

CONS

  1. kann von Anwendungen nicht zuverlässig "vorhergesagt" werden - kann nur nach dem INSERT abgerufen werden;
  2. benötigt ein komplexes Schema in Umgebungen mit mehreren Servern, da IDENTITY in einigen Formen der Replikation nicht erlaubt ist;
  3. kann dupliziert werden, wenn nicht explizit PRIMARY KEY festgelegt ist.
  4. Wenn ein Teil des gruppierten Index in der Tabelle vorhanden ist, kann dies einen Einfüge-Hotspot erzeugen;
  5. proprietär und nicht direkt tragbar;
  6. nur innerhalb einer einzigen Tabelle eindeutig;
  7. Lücken können auftreten (z. B. durch eine rückgängig gemachte Transaktion), und dies kann dazu führen, dass Alarme im Stil von Hühnern ausgelöst werden.

GUID

PROS

  1. Da sie {mehr oder weniger} garantiert eindeutig sind, können mehrere Tabellen / Datenbanken / Instanzen / Server / Netzwerke / Rechenzentren sie unabhängig voneinander erstellen und dann ohne Konflikte zusammenführen;

  2. erforderlich für einige Replikationsformen;

  3. kann außerhalb der Datenbank (z. B. durch eine Anwendung) erzeugt werden;
  4. verteilte Werte verhindern Hot-Spot (solange Sie diese Spalte nicht clustern, was zu einer ungewöhnlich hohen Fragmentierung führen kann).

CONS

  1. Der breitere Datentyp führt zu einem Rückgang der Indexleistung (wenn Clustering vorliegt, garantiert jeder Eintrag eine andere Seite "schmutzig") und erhöht die Speicheranforderungen.
  2. umständlich zu debuggen (wo userid = {BAE7DF4-DDF-3RG-5TY3E3RF456AS10});
  3. updatefähig (muss Änderungen propagieren oder die Aktivität komplett verhindern);
  4. empfindlich gegenüber Zeit-Rollbacks in bestimmten Umgebungen (z. B. Sommerzeit-Rollbacks);
  5. GROUP BY und andere Mengenoperationen erfordern oft CAST / CONVERT;
  6. nicht alle Sprachen und Umgebungen unterstützen direkt GUIDs;
  7. es gibt keine Aussage wie SCOPE_GUID (), um den Wert zu bestimmen, der erzeugt wurde, z. von NEWID ();
Muhammad Nasir 21.10.2016 15:58
quelle
2

Eine Sache, die Sie beim Entwerfen Ihrer Tabellen beachten sollten, ist, ob Sie Ihre Daten replizieren, sharden oder auf andere Weise von einem Ort zum anderen bewegen müssen. Vielleicht werden die Daten von anderen Anwendungen erzeugt und müssen mit Ihren Daten synchronisiert werden. Ein Beispiel hierfür wäre eine mobile App, die Daten erstellt und diese dann mit einem Server synchronisiert. Wenn etwas wie das ist oder könnte, dann würde UNIQUEIDENTIFIER die gute Wahl für Ihren Primärschlüssel verwenden.

Der UNIQUEIDENTIFIER -Datentyp ist für die Performance schrecklich, wenn er als gruppierter Index verwendet wird. Ja, Sie könnten newsequentialid() verwenden, aber das hilft Ihnen nicht, wenn die Werte auf anderen Geräten generiert werden. Der Konsens scheint zu sein, dass geclusterte Indizes am besten mit einem sequentiellen und engen Datentyp wie einem INT oder BIGINT verwendet werden.

Wenn Sie keine Probleme mit Speicherplatz haben, können Sie versuchen, eine Kombination aus einem IDENTITY Clusterschlüssel und UNIQUEIDENTIFIER Primärschlüssel zu verwenden. Erstellen Sie eine Spalte cluster key IDENTITY und verwenden Sie sie für Ihren Clustered-Index (jedoch nicht als Primärschlüssel). Die Inserts werden weiterhin sequentiell erstellt und erfüllen den Wunsch nach einem engen Datentyp. Jetzt können Sie UNIQUEIDENTIFIER als Primärschlüssel verwenden. Dadurch können Sie Ihre Daten bei Bedarf verschieben, replizieren und / oder sharden.

Der Clusterschlüssel hat keinen anderen Zweck, als Ihre Beilagen sequenziell zu halten und auf die alle anderen nicht gruppierten Indizes verweisen, wenn Sie nach Daten für eine bestimmte Abfrage suchen. Der cluster key ist vollständig weggeworfen und kann neu generiert werden, wenn Daten verschoben, repliziert und / oder geschichtet werden, da die Eindeutigkeit durch den Primärschlüssel UNIQUEIDENTIFIER behandelt wird.

Hier ist ein großartiger Artikel, der zeigt, was intern passiert, wenn Sie IDENTITY vs UNIQUEIDENTIFIER für Ihren Clustered-Index verwenden.

rmblstrp 04.11.2014 23:07
quelle
1

GUIDs sind groß, haben aber den Vorteil, überall einzigartig zu sein: diese Tabelle oder das, diesen Server oder das, wenn Sie die GUID haben, dann ist alles andere erkennbar. Wenn das für dich nützlich ist, dann ist es großartig, aber du wirst dafür in den Gemeinkosten zahlen und weiter zahlen, zahlen und bezahlen ....

Materialcodes funktionieren nur für kleinere unveränderliche Schlüssel, wie Farben oder Klassifizierungscodes und dergleichen. R wird immer rot sein, G wird grün, es ist ein Byte, usw.

Identitätsspalten kommen dann zur Geltung, wenn kein Materialcode vorhanden ist oder der natürliche Schlüssel aus mehreren Materialcodes besteht oder der natürliche Schlüssel bereits aus anderen Identitätsspalten und / oder GUIDs oder dem natürlichen Schlüssel besteht ist veränderbar. Ja, Sie könnten eine GUID verwenden, aber eine Integer-Spalte ist in jeder Hinsicht viel effizienter.

Eine weitere in SQL 2012 verfügbare Option sind Sequenzen, ähnlich einer Identitätsspalte auf Datenbankebene. Dies ist ein nettes Mittelding zwischen GUIDs und Identitätsspalten, in dem Sinne, dass eine Sequenz über viele Tabellen hinweg verwendet werden kann, so dass von einem gegebenen Wert nicht nur die Zeile, sondern auch die Tabelle erkennbar ist - aber Sie können sie trotzdem verwenden ein INT oder BIGINT (oder SMALLINT!), wenn Sie denken, dass dies für Ihre Daten ausreicht. Das ist für bestimmte Zwecke ziemlich nett, wie eine Objekt-ID in der OO-Welt.

Beachten Sie, dass viele oder die leichten ORMs erwarten, dass Tabellen einen einzelnen Primärschlüssel haben, vorzugsweise eine Ganzzahlspalte, und dass sie möglicherweise nur mit einem INT IDENTITY PK gut funktionieren.

    
Peter Radocchia 09.12.2013 05:59
quelle