GUID'er kan synes at være et naturligt valg for din primære nøgle - og hvis du virkelig skal, kan du sikkert argumentere for at bruge den til den PRIMÆRE NØGLE i tabellen. Hvad jeg kraftigt vil anbefale ikke at gøre er at bruge GUID-kolonnen som klyngenøgle , hvilket SQL Server gør som standard, medmindre du specifikt fortæller den ikke at gøre det.
Du skal virkelig holde to problemer adskilt:
-
den primære nøgle er en logisk konstruktion - en af kandidatnøglerne, der unikt og pålideligt identificerer hver række i din tabel. Dette kan være hvad som helst - en
INT
, enGUID
, en streng - vælg det, der giver mest mening for dit scenarie. -
klyngerøglen (den eller de kolonner, der definerer "klyngeindekset" i tabellen) - dette er en fysisk lagringsrelateret ting, og her er en lille, stabil, stadigt stigende datatype dit bedste valg -
INT
ellerBIGINT
som din standardindstilling.
Som standard bruges den primære nøgle på en SQL Server-tabel også som clustering-nøglen - men sådan behøver det ikke være! Jeg har personligt set massive præstationsgevinster, når den tidligere GUID-baserede primære/klyngede nøgle blev opdelt i to separate nøgler - den primære (logiske) nøgle på GUID'en og klynge- (bestillings-) nøglen på en separat INT IDENTITY(1,1)
kolonne.
Som Kimberly Tripp - The Queen of Indexing - og andre har sagt rigtig mange gange - en GUID
da klyngingsnøglen ikke er optimal, da den på grund af dens tilfældighed vil føre til massiv side- og indeksfragmentering og generelt dårlig ydeevne.
Ja, jeg ved det - der er newsequentialid()
i SQL Server 2005 og nyere - men selv det er ikke rigtig og fuldt sekventielt og lider derfor også af de samme problemer som GUID
- bare lidt mindre fremtrædende.
Så er der et andet problem at overveje:klyngingsnøglen på en tabel vil også blive tilføjet til hver eneste indgang på hvert ikke-klyngede indeks på din tabel - så du vil virkelig gerne sikre dig, at den er så lille som muligt. Typisk en INT
med 2+ milliarder rækker burde være tilstrækkeligt til langt de fleste tabeller - og sammenlignet med en GUID
som klyngenøgle kan du spare dig selv for hundredvis af megabyte lagerplads på disk og serverhukommelse.
Hurtig beregning - ved hjælp af INT
vs. GUID
som primær og klyngenøgle:
- Basistabel med 1.000.000 rækker (3,8 MB vs. 15,26 MB)
- 6 ikke-klyngede indekser (22,89 MB vs. 91,55 MB)
TOTALT:25 MB vs. 106 MB - og det er bare på et enkelt bord!
Lidt mere stof til eftertanke - fremragende ting af Kimberly Tripp - læs det, læs det igen, fordøj det! Det er virkelig SQL Server-indekseringsevangeliet.
- GUID'er som PRIMÆR NØGLE og/eller grupperet nøgle
- Debatten om klynget indeks fortsætter
- Stadig voksende klyngenøgle - The Clustered Index Debate...........igen!
- Diskplads er billig - det er ikke pointen!
PS:selvfølgelig, hvis du kun har at gøre med nogle få hundrede eller et par tusinde rækker - vil de fleste af disse argumenter ikke have den store indflydelse på dig. Men hvis du kommer ind i titusindvis eller hundredtusindvis af rækker, eller du begynder at tælle i millioner - så disse punkter bliver meget afgørende og meget vigtige at forstå.
Opdatering: hvis du vil have dit PKGUID
kolonne som din primære nøgle (men ikke din klyngenøgle) og en anden kolonne MYINT
(INT IDENTITY
) som din klyngenøgle - brug denne:
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)
Grundlæggende:du skal bare eksplicit fortæl PRIMARY KEY
begrænsning af, at det er NONCLUSTERED
(ellers er det oprettet som dit klyngede indeks, som standard) - og derefter opretter du et andet indeks, der er defineret som CLUSTERED
Dette vil virke - og det er en gyldig mulighed, hvis du har et eksisterende system, der skal "re-konstrueres" for ydeevne. For et nyt system, hvis du starter fra bunden, og du ikke er i et replikeringsscenarie, ville jeg altid vælge ID INT IDENTITY(1,1)
som min klyngede primærnøgle - meget mere effektiv end noget andet!