Identyfikatory GUID mogą wydawać się naturalnym wyborem dla klucza podstawowego — a jeśli naprawdę musisz, prawdopodobnie możesz argumentować, aby użyć go jako klucza podstawowego tabeli. Czego zdecydowanie odradzam nie robić używa kolumny GUID jako klucza klastrowania , co SQL Server robi domyślnie, chyba że wyraźnie zabronisz mu tego.
Naprawdę musisz oddzielić dwa problemy:
-
klucz podstawowy to konstrukcja logiczna — jeden z kluczy kandydujących, który jednoznacznie i niezawodnie identyfikuje każdy wiersz w tabeli. To może być naprawdę wszystko -
INT
,GUID
, ciąg — wybierz, co jest najbardziej sensowne dla Twojego scenariusza. -
klucz klastrowania (kolumna lub kolumny, które definiują „indeks klastrowy” w tabeli) — jest to fizyczny rzecz związana z pamięcią masową, a tutaj najlepszym wyborem jest mały, stabilny, stale rosnący typ danych -
INT
lubBIGINT
jako domyślną opcję.
Domyślnie klucz podstawowy w tabeli SQL Server jest również używany jako klucz klastrowy — ale nie musi tak być! Osobiście widziałem ogromny wzrost wydajności podczas dzielenia poprzedniego klucza podstawowego / klastrowego opartego na identyfikatorze GUID na dwa oddzielne klucze - klucz podstawowy (logiczny) w identyfikatorze GUID i klucz klastrowania (porządkujący) na oddzielnym INT IDENTITY(1,1)
kolumna.
Jak Kimberly Tripp - królowa indeksowania - i inni wielokrotnie stwierdzali - GUID
ponieważ klucz klastrowania nie jest optymalny, ponieważ ze względu na jego losowość doprowadzi do ogromnej fragmentacji stron i indeksów oraz ogólnie do złej wydajności.
Tak, wiem - jest newsequentialid()
w SQL Server 2005 i nowszych - ale nawet to nie jest prawdziwie i w pełni sekwencyjne, a zatem również cierpi na te same problemy, co GUID
- tylko trochę mniej widoczne.
Jest jeszcze jedna kwestia do rozważenia:klucz klastrowania w tabeli zostanie dodany do każdego wpisu w każdym indeksie nieklastrowanym w Twojej tabeli - dlatego naprawdę chcesz się upewnić, że jest on tak mały, jak to możliwe. Zazwyczaj INT
z ponad 2 miliardami wierszy powinno wystarczyć dla większości tabel - w porównaniu z GUID
jako klucz klastrowania możesz zaoszczędzić sobie setki megabajtów pamięci na dysku i w pamięci serwera.
Szybkie obliczenia - przy użyciu INT
w porównaniu z GUID
jako klucz podstawowy i klucz klastrowy:
- Tabela podstawowa z 1 000 000 wierszy (3,8 MB vs. 15,26 MB)
- 6 indeksów nieklastrowych (22,89 MB w porównaniu z 91,55 MB)
ŁĄCZNIE:25 MB vs. 106 MB - i to tylko na jednym stole!
Trochę więcej do myślenia - świetne rzeczy Kimberly Tripp - przeczytaj, przeczytaj jeszcze raz, przetrawij! To naprawdę ewangelia indeksowania SQL Server.
- identyfikatory GUID jako klucz podstawowy i/lub klucz klastrowy
- Debata o indeksach klastrowych trwa
- Ciągle rosnący klucz klastrowania – ponownie debata na temat indeksów klastrowych!
- Miejsce na dysku jest tanie – to nie o co chodzi!
PS:oczywiście, jeśli masz do czynienia z kilkoma setkami lub kilkoma tysiącami wierszy – większość z tych argumentów nie będzie miała na ciebie większego wpływu. Jednak:jeśli znajdziesz się w dziesiątkach lub setkach tysięcy wierszy lub zaczniesz liczyć w milionach - wtedy te punkty stają się bardzo ważne i bardzo ważne do zrozumienia.
Aktualizacja: jeśli chcesz mieć swój PKGUID
kolumna jako klucz podstawowy (ale nie klucz klastrowania), a kolejna kolumna MYINT
(INT IDENTITY
) jako klucz klastrowania - użyj tego:
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)
Zasadniczo:wystarczy wyraźnie powiedz PRIMARY KEY
ograniczenie, że jest NONCLUSTERED
(w przeciwnym razie jest tworzony domyślnie jako indeks klastrowy) — a następnie tworzysz drugi indeks zdefiniowany jako CLUSTERED
To zadziała – i jest to ważna opcja, jeśli masz istniejący system, który wymaga „przeprojektowania” pod kątem wydajności. W przypadku nowego systemu, jeśli zaczynasz od zera i nie jesteś w scenariuszu replikacji, zawsze wybieram ID INT IDENTITY(1,1)
jako mój klastrowany klucz podstawowy - znacznie bardziej wydajny niż cokolwiek innego!