GUIDs kan tyckas vara ett naturligt val för din primära nyckel - och om du verkligen måste, kan du förmodligen argumentera för att använda den för den PRIMÄRA KEY i tabellen. Vad jag starkt rekommenderar att inte gör använder kolumnen GUID som klustringsnyckel , vilket SQL Server gör som standard, om du inte specifikt säger åt den att inte göra det.
Du måste verkligen hålla isär två frågor:
-
den primära nyckeln är en logisk konstruktion - en av kandidatnycklarna som unikt och tillförlitligt identifierar varje rad i din tabell. Det här kan vara vad som helst - en
INT
, enGUID
, en sträng - välj det som är mest meningsfullt för ditt scenario. -
klustringsnyckeln (kolumnen eller kolumnerna som definierar det "klustrade indexet" i tabellen) - detta är ett fysiskt lagringsrelaterad sak, och här är en liten, stabil, ständigt ökande datatyp ditt bästa val -
INT
ellerBIGINT
som ditt standardalternativ.
Som standard används primärnyckeln på en SQL Server-tabell också som klustringsnyckel - men det behöver inte vara så! Jag har personligen sett enorma prestandavinster när jag delar upp den tidigare GUID-baserade primära / klustrade nyckeln i två separata nyckel - den primära (logiska) nyckeln på GUID och klustringsnyckeln (beställningsnyckeln på en separat INT IDENTITY(1,1)
kolumn.
Som Kimberly Tripp - the Queen of Indexing - och andra har sagt väldigt många gånger - en GUID
eftersom klustringsnyckeln inte är optimal, eftersom den på grund av dess slumpmässighet kommer att leda till massiv sida- och indexfragmentering och till allmänt dålig prestanda.
Ja, jag vet - det finns newsequentialid()
i SQL Server 2005 och uppåt - men även det är inte riktigt och helt sekventiellt och lider därmed också av samma problem som GUID
- bara lite mindre framträdande så.
Sedan finns det en annan fråga att tänka på:klustringsnyckeln på ett bord kommer att läggas till varje post på varje icke-klustrade index på ditt bord också - så du vill verkligen se till att den är så liten som möjligt. Vanligtvis en INT
med 2+ miljarder rader borde vara tillräckligt för de allra flesta tabeller - och jämfört med en GUID
som klustringsnyckel kan du spara hundratals megabyte lagringsutrymme på disk och serverminne.
Snabb beräkning - med INT
kontra GUID
som primär- och klustringsnyckel:
- Bastabell med 1 000 000 rader (3,8 MB mot 15,26 MB)
- 6 icke-klustrade index (22,89 MB mot 91,55 MB)
TOTALT:25 MB kontra 106 MB - och det är bara på ett enda bord!
Lite mer att tänka på - utmärkta grejer av Kimberly Tripp - läs det, läs det igen, smält det! Det är verkligen SQL Server-indexeringsevangeliet.
- GUIDs som PRIMÄRNYCKEL och/eller klustrad nyckel
- Debatten om klustrade index fortsätter
- Ständigt ökande klustringsnyckel - The Clustered Index Debate...........igen!
- Diskutrymme är billigt - det är inte poängen!
PS:självklart, om du bara har att göra med några hundra eller några tusen rader - kommer de flesta av dessa argument inte att ha någon större inverkan på dig. Men om du kommer in på tiotusentals eller hundratusentals rader, eller om du börjar räkna i miljoner - då dessa punkter blir mycket avgörande och mycket viktiga att förstå.
Uppdatering: om du vill ha ditt PKGUID
kolumn som din primära nyckel (men inte din klustringsnyckel), och en annan kolumn MYINT
(INT IDENTITY
) som din klustringsnyckel - använd denna:
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)
I grund och botten:du måste bara uttryckligen berätta för PRIMARY KEY
begränsning att den är NONCLUSTERED
(annars skapas det som ditt klustrade index, som standard) - och sedan skapar du ett andra index som är definierat som CLUSTERED
Detta kommer att fungera - och det är ett giltigt alternativ om du har ett befintligt system som behöver "omkonstrueras" för prestanda. För ett nytt system, om du börjar från början och du inte befinner dig i ett replikeringsscenario, skulle jag alltid välja ID INT IDENTITY(1,1)
som min klustrade primärnyckel - mycket effektivare än något annat!