GUID можуть здатися природним вибором для вашого первинного ключа - і якщо ви дійсно повинні, ви, ймовірно, можете заперечити використовувати його для ОСНОВНОГО КЛЮЧА таблиці. Я настійно не рекомендую цього робити - це використовувати стовпчик GUID як ключ кластеризації , який SQL Server робить за замовчуванням, якщо ви конкретно не скажете цього.
Дійсно потрібно тримати окремо два питання:
первинний ключ є логічною конструкцією - один з ключів - кандидатів , які однозначно і надійно ідентифікують кожен рядок в таблиці. Це може бути все що завгодно, насправді - INT
a GUID
, a, string - вибирайте те, що має найбільше значення для вашого сценарію.
ключ кластеризації (стовпець або стовпці , які визначають «кластерний індекс» на столі) - це фізичне зберігання пов'язаних річ, і тут, невеликий, стабільний, постійно збільшується тип даних ваш кращий вибір - INT
або BIGINT
як ваш опція за замовчуванням.
За замовчуванням первинний ключ таблиці SQL Server також використовується як ключ кластеризації - але це не повинно бути таким! Я особисто бачив значні підвищення продуктивності, коли розбивали попередній первинний / кластерний ключ на основі GUID на два окремі ключі - первинний (логічний) ключ GUID та кластеризаційний (замовляючий) ключ в окремому INT IDENTITY(1,1)
стовпчику.
Як Кімберлі Тріпп - Королева індексації - та інші багато разів заявляли - а, GUID
оскільки кластерний ключ не є оптимальним, оскільки через його випадковість це призведе до масивної фрагментації сторінок та індексів та загалом до поганої продуктивності.
Так, я знаю - є newsequentialid()
SQL Server 2005 і новіші версії, але навіть це не є справді і повністю послідовним, і, таким чином, також страждає від тих же проблем, що і GUID
- лише трохи менш помітно.
Тоді слід врахувати ще одне питання: ключ кластеризації в таблиці буде доданий до кожного запису кожного та кожного некластеризованого індексу вашої таблиці - таким чином, ви дійсно хочете переконатися, що він якнайменший. Як правило, для INT
2+ мільярдів рядків має бути достатньо для переважної більшості таблиць - і порівняно GUID
з клавішем клавіші, ви можете заощадити сотні мегабайт пам’яті на диску та в пам’яті сервера.
Швидкий розрахунок - використання INT
проти , GUID
як первинний і кластер Key:
- Базова таблиця з 1'000'000 рядками (3,8 Мб проти 15,26 МБ)
- 6 некластеризованих індексів (22,89 МБ проти 91,55 МБ)
ВСЕ: 25 МБ проти 106 МБ - і це просто на одному столі!
Ще трохи їжі для роздумів - відмінна штука Кімберлі Тріпп - читайте її, читайте її ще раз, перетравлюйте! Насправді це євангеліє з індексації SQL Server.
PS: Звичайно, якщо ви маєте справу лише з декількома сотнями або кількома тисячами рядків - більшість цих аргументів насправді не матимуть великого впливу на вас. Однак: якщо ти потрапив у десятки чи сотні тисяч рядків, або починаєш рахувати мільйони - то ці точки стають дуже важливими та дуже важливими для розуміння.
Оновлення: якщо ви хочете, щоб ваш PKGUID
стовпець був основним ключем (але не вашим кластеризуючим ключем), а інший стовпець MYINT
( INT IDENTITY
) як ваш кластерний ключ - використовуйте це:
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)
В основному: вам просто потрібно чітко сказати про PRIMARY KEY
обмеження, що воно є NONCLUSTERED
(інакше воно створюється як ваш кластерний індекс, за замовчуванням) - і тоді ви створюєте другий індекс, який визначається якCLUSTERED
Це буде спрацьовувати - і це допустимий варіант, якщо у вас є існуюча система, яку потрібно «переробити» для продуктивності. Для нової системи, якщо ви починаєте з нуля, і ви не в сценарії реплікації, я б завжди вибрав ID INT IDENTITY(1,1)
свій кластерний первинний ключ - набагато ефективніший за все інше!