I GUID possono sembrare una scelta naturale per la tua chiave primaria - e se davvero devi, potresti probabilmente discutere di usarla per la PRIMARY KEY della tabella. Quello che consiglio vivamente di non fare è usare la colonna GUID come chiave di clustering , che fa SQL Server per impostazione predefinita, a meno che non gli dica esplicitamente di non farlo.
Devi davvero tenere separati due problemi:
la chiave primaria è un costrutto logico, una delle chiavi candidate che identifica in modo univoco e affidabile ogni riga della tabella. Questo può essere qualsiasi cosa, davvero - an INT
, a GUID
, a string - scegli ciò che ha più senso per il tuo scenario.
la chiave di clustering (la colonna o le colonne che definiscono "l'indice di cluster" nella tabella) - questa è una cosa fisica correlata all'archiviazione e qui, un tipo di dati piccolo, stabile e in costante aumento è la scelta migliore - INT
o BIGINT
come il tuo opzione predefinita.
Per impostazione predefinita, la chiave primaria su una tabella di SQL Server viene utilizzata anche come chiave di clustering, ma non è necessario che sia così! Ho visto personalmente enormi miglioramenti delle prestazioni quando ho suddiviso la precedente chiave primaria / cluster basata su GUID in due chiavi separate: la chiave primaria (logica) sul GUID e la chiave di raggruppamento (ordinamento) su una INT IDENTITY(1,1)
colonna separata .
Come Kimberly Tripp - la regina dell'indicizzazione - e altri hanno affermato molte volte - a GUID
poiché la chiave di clustering non è ottimale, poiché a causa della sua casualità, porterà a una massiccia frammentazione di pagine e indici e a prestazioni generalmente scarse.
Sì, lo so - c'è newsequentialid()
in SQL Server 2005 e versioni successive - ma anche questo non è veramente e completamente sequenziale e quindi soffre anche degli stessi problemi del GUID
- solo un po 'meno evidentemente.
Quindi c'è un altro problema da considerare: la chiave di clustering su una tabella verrà aggiunta a ogni singola voce su ogni indice non cluster anche sulla tabella - quindi vuoi davvero assicurarti che sia il più piccolo possibile. In genere, un INT
con oltre 2 miliardi di righe dovrebbe essere sufficiente per la stragrande maggioranza delle tabelle - e rispetto a un GUID
come chiave di clustering, è possibile salvare centinaia di megabyte di spazio di archiviazione su disco e nella memoria del server.
Calcolo rapido - usando INT
vs. GUID
come chiave primaria e di cluster:
- Tabella di base con 1'000'000 righe (3,8 MB contro 15,26 MB)
- 6 indici non cluster (22,89 MB contro 91,55 MB)
TOTALE: 25 MB contro 106 MB - e questo è solo su un singolo tavolo!
Ancora un po 'di spunti di riflessione - materiale eccellente di Kimberly Tripp - leggilo, rileggilo, digeriscilo! È il vangelo dell'indicizzazione di SQL Server, davvero.
PS: ovviamente, se hai a che fare solo con poche centinaia o poche migliaia di righe, la maggior parte di questi argomenti non avrà un grande impatto su di te. Tuttavia: se entri nelle decine o centinaia di migliaia di righe o inizi a contare in milioni - allora quei punti diventano molto cruciali e molto importanti da capire.
Aggiornamento: se si desidera avere la PKGUID
colonna come chiave primaria (ma non la chiave di clustering) e un'altra colonna MYINT
( INT IDENTITY
) come chiave di clustering, utilizzare questo:
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)
Fondamentalmente: devi solo dire esplicitamente il PRIMARY KEY
vincolo che è NONCLUSTERED
(altrimenti viene creato come indice cluster, per impostazione predefinita) - e quindi creare un secondo indice definito comeCLUSTERED
Funzionerà - ed è un'opzione valida se si dispone di un sistema esistente che deve essere "riprogettato" per le prestazioni. Per un nuovo sistema, se inizi da zero e non ti trovi in uno scenario di replica, sceglierei sempre ID INT IDENTITY(1,1)
la mia chiave primaria in cluster, molto più efficiente di ogni altra cosa!