GUIDs scheinen 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 PRIMARY KEY der Tabelle zu verwenden. Was ich dringend empfehlen würde nicht zu tun ist die Verwendung der GUID-Spalte als Bündelungsschlüssel was SQL Server standardmäßig tut, es sei denn, Sie weisen ihn ausdrücklich an, dies nicht zu tun.
Sie müssen zwei Themen wirklich auseinander halten:
-
die Primärschlüssel ist ein logisches Konstrukt - einer der Kandidatenschlüssel, der jede Zeile in Ihrer Tabelle eindeutig und zuverlässig identifiziert. Dies kann wirklich alles sein - ein INT
, a GUID
Wählen Sie aus, was für Ihr Szenario am sinnvollsten ist.
-
die Bündelungsschlüssel (die Spalte(n), die den "geclusterten Index" der Tabelle definieren) - dies ist ein physisch und hier ist ein kleiner, stabiler, ständig wachsender Datentyp die beste Wahl - INT
o BIGINT
als Ihre Standardoption.
Standardmäßig wird der Primärschlüssel einer SQL Server-Tabelle auch als Clustering-Schlüssel verwendet - das muss aber nicht so sein! Ich persönlich habe massive Leistungssteigerungen festgestellt, als ich den bisherigen GUID-basierten Primär-/Clustering-Schlüssel in zwei separate Schlüssel auflöste - den primären (logischen) Schlüssel auf der GUID und den Clustering-Schlüssel (Ordnungsschlüssel) auf einem separaten INT IDENTITY(1,1)
Spalte.
Als Kimberly Tripp - die Königin der Indizierung - und andere haben es schon oft gesagt - eine GUID
als Clustering-Schlüssel ist nicht optimal, da er aufgrund seiner Zufälligkeit zu einer massiven Seiten- und Indexfragmentierung und zu einer allgemein schlechten Leistung führt.
Ja, ich weiß - es gibt newsequentialid()
in SQL Server 2005 und höher - aber auch das ist nicht wirklich und vollständig sequentiell und leidet daher unter denselben Problemen wie die GUID
- nur etwas weniger auffällig.
Dann gibt es noch einen weiteren Punkt zu bedenken: Der Clustering-Schlüssel einer Tabelle wird zu jedem einzelnen Eintrag in jedem nicht geclusterten Index Ihrer Tabelle hinzugefügt - Sie sollten also sicherstellen, dass er so klein wie möglich ist. Typischerweise wird ein INT
mit 2+ Milliarden Zeilen sollte für die große Mehrheit der Tabellen ausreichen - und im Vergleich zu einer GUID
als Clustering-Schlüssel verwenden, können Sie Hunderte von Megabyte an Speicherplatz auf der Festplatte und im Serverspeicher sparen.
Schnelle Berechnung - mit INT
vs. GUID
als Primär- und Clustering-Schlüssel:
- Basistabelle mit 1'000'000 Zeilen (3.8 MB vs. 15.26 MB)
- 6 nicht geclusterte Indizes (22,89 MB vs. 91,55 MB)
TOTAL: 25 MB vs. 106 MB - und das bei nur einem einzigen Tisch!
Ein paar weitere Denkanstöße - exzellentes Material von Kimberly Tripp - lesen Sie es, lesen Sie es noch einmal, verdauen Sie es! Es ist das Evangelium der SQL Server-Indizierung, wirklich.
PS: Wenn Sie nur mit ein paar hundert oder tausend Zeilen zu tun haben, haben die meisten dieser Argumente natürlich keine großen Auswirkungen auf Sie. Wenn Sie jedoch mit zehn- oder hunderttausenden von Zeilen zu tun haben, oder wenn Sie anfangen, in Millionen zu zählen dann Diese Punkte sind von entscheidender Bedeutung und sehr wichtig zu verstehen.
Update: wenn Sie Ihre PKGUID
Spalte als Primärschlüssel (aber nicht als Clustering-Schlüssel), und eine weitere Spalte MYINT
( INT IDENTITY
) als Ihren Clustering-Schlüssel - verwenden Sie diesen:
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 ausdrücklich sagen die PRIMARY KEY
Einschränkung, dass es sich um NONCLUSTERED
(andernfalls wird er standardmäßig als Ihr geclusterter Index erstellt) - und dann erstellen Sie einen zweiten Index, der definiert ist als CLUSTERED
Das funktioniert - und ist eine gute Option, wenn Sie ein bestehendes System haben, das für mehr Leistung "überarbeitet" werden muss. Bei einem neuen System, wenn Sie von Grund auf neu anfangen und sich nicht in einem Replikationsszenario befinden, würde ich mich immer für ID INT IDENTITY(1,1)
als geclusterter Primärschlüssel - viel effizienter als alles andere!