Os GUIDs podem parecer uma escolha natural para sua chave primária - e se você realmente precisar, provavelmente poderá argumentar para usá-la na CHAVE PRIMÁRIA da tabela. O que eu recomendo fortemente não fazer é usar a coluna GUID como a chave de cluster , o que o SQL Server faz por padrão, a menos que você diga especificamente que não.
Você realmente precisa manter dois problemas separados:
a chave primária é uma construção lógica - uma das chaves candidatas que identifica de maneira exclusiva e confiável todas as linhas da sua tabela. Isso pode ser qualquer coisa, realmente - uma INT
, uma GUID
, uma sequência - escolha o que faz mais sentido para o seu cenário.
a chave de cluster (a coluna ou colunas que definem o "índice de cluster" na tabela) - isso é relacionado ao armazenamento físico e, aqui, um tipo de dados pequeno, estável e sempre crescente é a melhor opção - INT
ou BIGINT
como opção padrão.
Por padrão, a chave primária em uma tabela do SQL Server também é usada como chave de cluster - mas isso não precisa ser assim! Eu, pessoalmente, vi ganhos de desempenho maciços ao dividir a Chave Primária / Clusterizada baseada em GUID anterior em duas chaves separadas - a chave primária (lógica) no GUID e a chave de agrupamento (ordem) em uma INT IDENTITY(1,1)
coluna separada .
Como Kimberly Tripp - a rainha da indexação - e outras já declararam muitas vezes - GUID
a chave de cluster não é ideal, pois, devido à sua aleatoriedade, levará a uma fragmentação maciça de páginas e índices e a um desempenho geralmente ruim.
Sim, eu sei - existe newsequentialid()
no SQL Server 2005 e acima - mas mesmo isso não é verdadeira e totalmente seqüencial e, portanto, também sofre dos mesmos problemas que os GUID
- apenas um pouco menos proeminentemente.
Depois, há outra questão a considerar: a chave de cluster em uma tabela será adicionada a toda e qualquer entrada em todo e qualquer índice não em cluster da sua tabela - assim, você realmente deseja garantir que seja o menor possível. Normalmente, um INT
com mais de 2 bilhões de linhas deve ser suficiente para a grande maioria das tabelas - e comparado a uma GUID
chave de cluster, você pode economizar centenas de megabytes de armazenamento em disco e na memória do servidor.
Cálculo rápido - usando INT
vs. GUID
como chave primária e de cluster:
- Tabela base com 1'000'000 linhas (3,8 MB vs. 15,26 MB)
- 6 índices não clusterizados (22,89 MB vs. 91,55 MB)
TOTAL: 25 MB vs. 106 MB - e isso é apenas uma tabela!
Um pouco mais de reflexão - coisas excelentes de Kimberly Tripp - leia, leia novamente, digera! É o evangelho de indexação do SQL Server, na verdade.
PS: é claro, se você estiver lidando com apenas algumas centenas ou milhares de linhas - a maioria desses argumentos não terá muito impacto sobre você. No entanto: se você entrar em dezenas ou centenas de milhares de linhas, ou você comece a contar em milhões - , em seguida, os pontos tornam-se muito crucial e muito importante para entender.
Atualização: se você deseja que sua PKGUID
coluna seja sua chave primária (mas não sua chave de cluster) e outra coluna MYINT
( INT IDENTITY
) como sua chave de cluster - use isto:
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)
Basicamente: você só precisa dizer explicitamente a PRIMARY KEY
restrição de que está NONCLUSTERED
(caso contrário, é criado como seu índice clusterizado, por padrão) - e então cria um segundo índice definido comoCLUSTERED
Isso funcionará - e é uma opção válida se você tiver um sistema existente que precise ser "reprojetado" para obter desempenho. Para um novo sistema, se você começar do zero e não estiver em um cenário de replicação, sempre escolheria ID INT IDENTITY(1,1)
como minha chave primária em cluster - muito mais eficiente do que qualquer outra coisa!