sql >> Database >  >> RDS >> Sqlserver

Wat zijn de best practices voor het gebruik van een GUID als primaire sleutel, met name met betrekking tot prestaties?

GUID's lijken misschien een natuurlijke keuze voor uw primaire sleutel - en als het echt moet, zou u waarschijnlijk kunnen argumenteren om het te gebruiken voor de PRIMARY KEY van de tabel. Wat ik sterk zou aanraden niet te doen is gebruik de GUID-kolom als de clustersleutel , wat SQL Server standaard doet, tenzij u specifiek aangeeft dat niet te doen.

Je moet echt twee zaken uit elkaar houden:

  1. de primaire sleutel is een logische constructie - een van de kandidaatsleutels die elke rij in uw tabel op unieke en betrouwbare wijze identificeert. Dit kan werkelijk van alles zijn - een INT , een GUID , een tekenreeks - kies wat het meest logisch is voor uw scenario.

  2. de clustersleutel (de kolom of kolommen die de "geclusterde index" in de tabel definiëren) - dit is een fysiek opslaggerelateerd ding, en hier is een klein, stabiel, steeds groter wordend gegevenstype de beste keuze - INT of BIGINT als uw standaardoptie.

Standaard wordt de primaire sleutel op een SQL Server-tabel ook gebruikt als de clustersleutel - maar dat hoeft niet zo te zijn! Ik heb persoonlijk enorme prestatieverbeteringen gezien bij het opsplitsen van de vorige op GUID gebaseerde primaire / geclusterde sleutel in twee afzonderlijke sleutels - de primaire (logische) sleutel op de GUID en de clustering (bestel) sleutel op een afzonderlijke INT IDENTITY(1,1) kolom.

Zoals Kimberly Tripp - de koningin van indexering - en anderen heel vaak hebben verklaard - een GUID omdat de clustersleutel niet optimaal is, omdat deze vanwege zijn willekeur tot enorme pagina- en indexfragmentatie en tot over het algemeen slechte prestaties leidt.

Ja, ik weet het - er is newsequentialid() in SQL Server 2005 en hoger - maar zelfs dat is niet echt en volledig sequentieel en lijdt dus ook aan dezelfde problemen als de GUID - alleen een beetje minder prominent dus.

Dan is er nog een ander probleem om te overwegen:de clustersleutel op een tabel wordt ook toegevoegd aan elk item op elke niet-geclusterde index op uw tabel - dus u wilt er zeker van zijn dat deze zo klein mogelijk is. Meestal is een INT met 2+ miljard rijen zou voldoende moeten zijn voor de overgrote meerderheid van tabellen - en vergeleken met een GUID als clustersleutel kunt u uzelf honderden megabytes aan opslagruimte besparen op schijf en in het servergeheugen.

Snelle berekening - met behulp van INT vs. GUID als primaire en clustersleutel:

  • Basistabel met 1.000.000 rijen (3,8 MB vs. 15,26 MB)
  • 6 niet-geclusterde indexen (22,89 MB vs. 91,55 MB)

TOTAAL:25 MB versus 106 MB - en dat is slechts op een enkele tafel!

Nog wat stof tot nadenken - uitstekende dingen van Kimberly Tripp - lees het, lees het opnieuw, verwerk het! Het is eigenlijk het SQL Server-indexeringsevangelie.

  • GUID's als PRIMAIRE SLEUTEL en/of geclusterde sleutel
  • Het debat over geclusterde indexen gaat door
  • Steeds toenemende clusteringsleutel - het geclusterde indexdebat..........nogmaals!
  • Schijfruimte is goedkoop - dat is niet het punt!

PS:natuurlijk, als je te maken hebt met slechts een paar honderd of een paar duizend rijen, zullen de meeste van deze argumenten niet echt veel invloed op je hebben. Echter:als je in de tien- of honderdduizenden rijen komt, of je begint te tellen in miljoenen - dan die punten worden heel cruciaal en heel belangrijk om te begrijpen.

Bijwerken: als je je PKGUID . wilt hebben kolom als uw primaire sleutel (maar niet uw clustersleutel), en een andere kolom MYINT (INT IDENTITY ) als uw clustersleutel - gebruik dit:

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)

Kortom:u hoeft alleen expliciet vertel de PRIMARY KEY beperking dat het NONCLUSTERED . is (anders wordt het standaard gemaakt als uw geclusterde index) - en vervolgens maakt u een tweede index die is gedefinieerd als CLUSTERED

Dit zal werken - en het is een geldige optie als je een bestaand systeem hebt dat moet worden "opnieuw ontworpen" voor prestaties. Voor een nieuw systeem, als je helemaal opnieuw begint en je zit niet in een replicatiescenario, dan zou ik altijd ID INT IDENTITY(1,1) kiezen als mijn geclusterde primaire sleutel - veel efficiënter dan wat dan ook!



  1. Doe met ons mee voor een introductie tot toegang met SQL Server

  2. Maak een draaitabel met PostgreSQL

  3. 4 tips voor het instellen van uw SQL Server-waarschuwingen

  4. Hoe de SQL Server SOUNDEX()-functie werkt