sql >> Database teknologi >  >> RDS >> Sqlserver

Hvad er den bedste praksis for at bruge en GUID som en primær nøgle, specifikt med hensyn til ydeevne?

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:

  1. 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 , en GUID , en streng - vælg det, der giver mest mening for dit scenarie.

  2. 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 eller BIGINT 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 - 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!



  1. MySQL bruger ikke indekser med WHERE IN-klausulen?

  2. SQRT() Funktion i Oracle

  3. Får du ugenummer fra en dato i MS SQL Server 2005?

  4. LEAD og LAG analytiske funktioner