Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Was sind die Best Practices für die Verwendung einer GUID als Primärschlüssel, insbesondere in Bezug auf die Leistung?

GUIDs scheinen eine natürliche Wahl für Ihren Primärschlüssel zu sein - und wenn Sie es wirklich müssen, könnten Sie wahrscheinlich argumentieren, sie für den PRIMARY KEY der Tabelle zu verwenden. Was ich dringend empfehlen würde nicht zu tun Verwenden Sie die GUID-Spalte als Clustering-Schlüssel , was SQL Server standardmäßig tut, es sei denn, Sie weisen ausdrücklich darauf hin.

Sie müssen wirklich zwei Dinge auseinanderhalten:

  1. der Primärschlüssel ist ein logisches Konstrukt – einer der Schlüsselkandidaten, der jede Zeile in Ihrer Tabelle eindeutig und zuverlässig identifiziert. Das kann wirklich alles sein - ein INT , eine GUID , eine Zeichenfolge - wählen Sie aus, was für Ihr Szenario am sinnvollsten ist.

  2. der Clustering-Schlüssel (die Spalte oder Spalten, die den "clustered index" in der Tabelle definieren) - dies ist ein physischer speicherbezogene Sache, und hier ist ein kleiner, stabiler, ständig wachsender Datentyp Ihre beste Wahl - INT oder BIGINT als Ihre Standardoption.

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

Wie Kimberly Tripp – die Königin der Indizierung – und andere schon oft gesagt haben – eine GUID da der Clustering-Schlüssel nicht optimal ist, da er aufgrund seiner Zufälligkeit zu einer massiven Seiten- und Indexfragmentierung und zu allgemein schlechter Leistung führt.

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

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

Schnelle Berechnung - mit INT vs. GUID als Primär- und Clusterschlüssel:

  • Basistabelle mit 1.000.000 Zeilen (3,8 MB vs. 15,26 MB)
  • 6 Nonclustered-Indizes (22,89 MB gegenüber 91,55 MB)

GESAMT:25 MB gegenüber 106 MB - und das nur auf einem einzigen Tisch!

Noch ein paar Denkanstöße - ausgezeichnetes Material von Kimberly Tripp - lesen Sie es, lesen Sie es noch einmal, verdauen Sie es! Es ist wirklich das Evangelium der SQL Server-Indizierung.

  • GUIDs als PRIMARY KEY und/oder Clustered Key
  • Die Debatte über Cluster-Indizes geht weiter
  • Ständig wachsender Clustering-Schlüssel - die Clustered-Index-Debatte..........schon wieder!
  • Speicherplatz ist billig - das ist nicht der Punkt!

PS:Natürlich, wenn Sie es nur mit ein paar hundert oder ein paar tausend Zeilen zu tun haben, werden die meisten dieser Argumente nicht wirklich viel Einfluss auf Sie haben. Aber:Wenn Sie in die Zehn- oder Hunderttausende von Zeilen geraten oder anfangen, in Millionen zu zählen - dann diese Punkte sind sehr wichtig und sehr wichtig zu verstehen.

Aktualisierung: wenn Sie Ihre PKGUID haben möchten Spalte als Ihren Primärschlüssel (aber nicht Ihren Gruppierungsschlüssel) und eine weitere Spalte MYINT (INT IDENTITY ) als Ihren Gruppierungsschlüssel - verwenden Sie dies:

CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
 MyINT INT IDENTITY(1,1) NOT NULL,
 .... add more columns as needed ...... )

ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)

CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)

Grundsätzlich gilt:Sie müssen nur explizit sagen Sie den PRIMARY KEY Einschränkung, dass es NONCLUSTERED ist (Andernfalls wird er standardmäßig als Ihr gruppierter Index erstellt) – und dann erstellen Sie einen zweiten Index, der als CLUSTERED definiert ist

Dies wird funktionieren - und es ist eine gültige Option, wenn Sie ein vorhandenes System haben, das für die Leistung "überarbeitet" werden muss. Wenn Sie bei einem neuen System bei Null anfangen und sich nicht in einem Replikationsszenario befinden, würde ich immer ID INT IDENTITY(1,1) auswählen als mein gruppierter Primärschlüssel - viel effizienter als alles andere!