Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Quais são as melhores práticas para usar um GUID como chave primária, especificamente em relação ao desempenho?


Os GUIDs podem parecer uma escolha natural para sua chave primária - e se você realmente precisar, provavelmente poderá argumentar para usá-lo para a CHAVE PRIMÁRIA da tabela. O que eu recomendo fortemente não fazer é usar a coluna GUID como a chave de cluster , que o SQL Server faz por padrão, a menos que você diga especificamente para não fazer isso.

Você realmente precisa manter duas questões separadas:

  1. a chave primária é uma construção lógica - uma das chaves candidatas que identifica de forma única e confiável cada linha em sua tabela. Isso pode ser qualquer coisa, realmente - um INT , um GUID , uma string - escolha o que faz mais sentido para o seu cenário.

  2. a chave de cluster (a coluna ou colunas que definem o "índice clusterizado" na tabela) - este é um físico coisa relacionada ao armazenamento, e aqui, um tipo de dados pequeno, estável e cada vez maior é sua melhor escolha - INT ou BIGINT como sua 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 não precisa ser assim! Eu pessoalmente vi enormes ganhos de desempenho 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 cluster (ordenação) em uma INT IDENTITY(1,1) coluna.

Como Kimberly Tripp - a Rainha da Indexação - e outros afirmaram muitas vezes - um GUID como a chave de clustering não é ideal, pois devido à sua aleatoriedade, levará a uma fragmentação massiva de página e índice e a um desempenho geralmente ruim.

Sim, eu sei - há newsequentialid() no SQL Server 2005 e superior - mas mesmo isso não é verdadeira e totalmente sequencial e, portanto, também sofre dos mesmos problemas que o GUID - apenas um pouco menos proeminente assim.

Depois, há outro problema a considerar:a chave de cluster em uma tabela também será adicionada a cada entrada em cada índice não clusterizado em sua tabela - portanto, 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 um GUID como 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 x 15,26 MB)
  • 6 índices não clusterizados (22,89 MB x 91,55 MB)

TOTAL:25 MB x 106 MB - e isso é apenas em uma única mesa!

Mais alguma coisa para pensar - material excelente de Kimberly Tripp - leia, leia novamente, digira! É o evangelho da indexação do SQL Server, na verdade.
  • GUIDs como PRIMARY KEY e/ou chave clusterizada
  • O debate sobre o índice clusterizado continua
  • Chave de clustering cada vez maior - o Debate sobre Índices Agrupados..........novamente!
  • O espaço em disco é barato - isso não o ponto!

PS:claro, se você estiver lidando com apenas algumas centenas ou alguns milhares de linhas - a maioria desses argumentos não terá muito impacto em você. No entanto:se você chegar às dezenas ou centenas de milhares de linhas ou começar a contar em milhões - então esses pontos se tornam muito cruciais e muito importantes para entender.

Atualização: se você quiser ter seu PKGUID coluna como 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 explicitamente informe a PRIMARY KEY restrição de que é NONCLUSTERED (caso contrário, é criado como seu índice clusterizado, por padrão) - e, em seguida, você cria um segundo índice definido como CLUSTERED

Isso funcionará - e é uma opção válida se você tiver um sistema existente que precise ser "reprojetado" para desempenho. Para um novo sistema, se você começar do zero e não estiver em um cenário de replicação, eu sempre escolheria ID INT IDENTITY(1,1) como minha chave primária em cluster - muito mais eficiente do que qualquer outra coisa!