Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Какви са най-добрите практики за използване на GUID като първичен ключ, по-специално по отношение на производителността?

GUID може да изглежда естествен избор за вашия първичен ключ - и ако наистина трябва, вероятно бихте могли да спорите да го използвате за ПЪРВИЧНИЯ КЛЮЧ на таблицата. Какво силно препоръчвам да не се прави е да използвате колоната GUID като ключ за клъстериране , което SQL Server прави по подразбиране, освен ако изрично не му кажете да не го прави.

Наистина трябва да разграничите два проблема:

  1. първичния ключ е логическа конструкция - един от кандидат ключовете, който уникално и надеждно идентифицира всеки ред във вашата таблица. Това може да бъде всичко, наистина - INT , GUID , низ - изберете това, което има най-голям смисъл за вашия сценарий.

  2. ключът за групиране (колоната или колоните, които дефинират "клъстерирания индекс" в таблицата) - това е физически нещо, свързано със съхранението, и тук най-добрият ви избор е малък, стабилен, непрекъснато нарастващ тип данни - INT или BIGINT като опция по подразбиране.

По подразбиране първичният ключ в таблица на SQL Server също се използва като ключ за клъстериране - но това не е необходимо да е така! Аз лично видях огромни печалби в производителността при разделянето на предишния основен/клъстериран ключ, базиран на GUID, на два отделни ключа - първичния (логически) ключ на GUID и ключ за групиране (подреждане) на отделен INT IDENTITY(1,1) колона.

Както Кимбърли Трип - кралицата на индексирането - и други са заявявали много пъти - GUID тъй като ключът за клъстериране не е оптимален, тъй като поради своята произволност ще доведе до масивна фрагментация на страници и индекси и като цяло до лоша производителност.

Да, знам - има newsequentialid() в SQL Server 2005 и по-нова версия - но дори това не е наистина и напълно последователно и по този начин също страда от същите проблеми като GUID - само малко по-слабо.

След това има още един проблем, който трябва да обмислите:ключът за клъстериране на таблица ще бъде добавен към всеки запис във всеки неклъстериран индекс във вашата таблица - по този начин наистина искате да сте сигурни, че е възможно най-малък. Обикновено INT с 2+ милиарда реда би трябвало да е достатъчно за по-голямата част от таблиците - и в сравнение с GUID като ключ за клъстериране можете да си спестите стотици мегабайта място за съхранение на диск и в паметта на сървъра.

Бързо изчисление - с помощта на INT срещу GUID като първичен и клъстериращ ключ:

  • Основна таблица с 1 000 000 реда (3,8 MB срещу 15,26 MB)
  • 6 неклъстерирани индекса (22,89 MB срещу 91,55 MB)

ОБЩО:25 MB срещу 106 MB - и това е само на една маса!

Още малко храна за размисъл - отлични неща от Кимбърли Трип - прочетете го, прочетете го отново, усвоете го! Това наистина е евангелието за индексиране на SQL Server.

  • GUID като PRIMARY KEY и/или клъстерен ключ
  • Дебатът за групирания индекс продължава
  • Непрекъснато нарастващ ключ за клъстериране – дебатът за групирания индекс ......... отново!
  • Пространството на диска е евтино – това е не въпросът!

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) като моят клъстериран първичен ключ - много по-ефективен от всичко друго!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да премахнете водещото празно пространство в SQL Server – LTRIM()

  2. Как да създадете уникално ограничение за множество колони в SQL Server - SQL Server / TSQL урок, част 96

  3. Как да активирате улавянето на промяна на данни (CDC) в база данни в SQL Server - урок за SQL Server

  4. Как да заредя XML файл в база данни с помощта на SSIS пакет?

  5. Върнете текущото име за влизане в SQL Server (T-SQL)