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

Eu tenho um aplicativo que usa GUID como a chave primária em quase todas as tabelas e li que existem problemas sobre o desempenho ao usar o GUID como chave primária. Honestamente, eu não vi nenhum problema, mas estou prestes a iniciar um novo aplicativo e ainda quero usar os GUIDs como as chaves primárias, mas eu estava pensando em usar uma chave primária composta (o GUID e talvez outro campo .)

Eu estou usando um GUID porque eles são agradáveis ​​e fáceis de gerenciar quando você tem diferentes ambientes, como bancos de dados de “produção”, “teste” e “dev”, e também para dados de migration entre bancos de dados.

Vou usar o Entity Framework 4.3 e quero atribuir o Guid no código do aplicativo, antes de inseri-lo no database. (isto é, eu não quero deixar o SQL gerar o Guid).

Qual é a prática recomendada para criar chaves primárias baseadas em GUID para evitar os supostos hits de desempenho associados a essa abordagem?

    Os GUIDs podem parecer uma escolha natural para a sua chave primária – e se você realmente precisar, você provavelmente poderia argumentar para usá-la na PRIMARY KEY 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 que não.

    Você realmente precisa manter dois problemas separados:

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

    2. a chave de clustering (a coluna ou colunas que definem o “índice clusterizado” na tabela) – isso é uma coisa relacionada ao armazenamento físico e, aqui, um tipo de dados pequeno, estável e crescente é 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 a chave de cluster – mas isso não precisa ser assim! Eu pessoalmente vi ganhos de desempenho em massa ao dividir a chave primária / clusterizada baseada em GUID anterior em duas chaves separadas – a chave primária (lógica) no GUID ea chave de clustering (ordenação) em uma INT IDENTITY(1,1) separada INT IDENTITY(1,1) coluna.

    Como Kimberly Tripp – a Rainha da Indexação – e outros já afirmaram muitas vezes – um GUID já que a chave de cluster não é a ideal, já que devido à sua aleatoriedade, levará a uma massiva fragmentação de páginas e índices e a um desempenho geralmente ruim.

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

    Em seguida, há outro problema a ser considerado: a chave de cluster em uma tabela será adicionada a todas as inputs de cada índice não agrupado em sua tabela também – portanto, você realmente deseja ter certeza de que é 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 a chave de cluster, você pode economizar centenas de megabytes de armazenamento no disco e na memory do servidor.

    Cálculo rápido – usando INT vs. GUID como Chave Primária e Clusterizada:

    • 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 em uma única mesa!

    Mais uma coisa para pensar – coisas excelentes de Kimberly Tripp – leia, leia de novo, digira! É o evangelho de indexação do SQL Server, na verdade.

    • GUIDs como PRIMARY KEY e / ou chave agrupada
    • O debate do índice em cluster continua
    • Chave de clustering crescente – o Debate de Clustered Index ………. novamente!
    • O espaço em disco é barato – esse não é o ponto!

    PS: claro, se você está lidando com apenas algumas centenas ou alguns milhares de linhas – a maioria desses argumentos não terá muito impacto sobre você. No entanto: se você entrar nas 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ê deseja ter sua coluna PKGUID 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 informar explicitamente a restrição PRIMARY KEY que é NONCLUSTERED (caso contrário, ela é criada como seu índice clusterizado, por padrão) – e então você cria um segundo índice que é 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, sempre escolho ID INT IDENTITY(1,1) como minha chave primária em cluster – muito mais eficiente do que qualquer outra coisa!

    Eu tenho usado GUIDs como PKs desde 2005. Neste mundo de database distribuído, é absolutamente a melhor maneira de mesclar dados distribuídos. Você pode triggersr e esquecer tabelas de mesclagem sem toda a preocupação de ints correspondentes em tabelas unidas. Juntas GUIDs podem ser copiadas sem qualquer preocupação.

    Esta é a minha configuração para usar os GUIDs:

    1. PK = GUID. Os GUIDs são indexados de maneira semelhante às strings, portanto, as tabelas de linhas superiores (mais de 50 milhões de registros) podem precisar do particionamento de tabelas ou de outras técnicas de desempenho. O SQL Server está se tornando extremamente eficiente, portanto, as preocupações com desempenho são cada vez menos aplicáveis.

    2. PK Guid é um índice não-clusterizado. Nunca cluster índice de um GUID, a menos que seja NewSequentialID. Mas, mesmo assim, uma reboot do servidor causará grandes interrupções no pedido.

    3. Adicione o ClusterID Int a todas as tabelas. Este é o seu índice CLUSTERED … que ordena sua mesa.

    4. Participar de ClusterIDs (int) é mais eficiente, mas eu trabalho com 20 a 30 milhões de tabelas de registro, portanto, ingressar em GUIDs não afeta visivelmente o desempenho. Se você quiser desempenho máximo, use o conceito ClusterID como sua chave principal e ingresse no ClusterID.

    Aqui está a minha tabela de E-mail …

     CREATE TABLE [Core].[Email] ( [EmailID] UNIQUEIDENTIFIER CONSTRAINT [DF_Email_EmailID] DEFAULT (newsequentialid()) NOT NULL, [EmailAddress] NVARCHAR (50) CONSTRAINT [DF_Email_EmailAddress] DEFAULT ('') NOT NULL, [CreatedDate] DATETIME CONSTRAINT [DF_Email_CreatedDate] DEFAULT (getutcdate()) NOT NULL, [ClusterID] INT NOT NULL IDENTITY, CONSTRAINT [PK_Email] PRIMARY KEY NonCLUSTERED ([EmailID] ASC) ); GO CREATE UNIQUE CLUSTERED INDEX [IX_Email_ClusterID] ON [Core].[Email] ([ClusterID]) GO CREATE UNIQUE NonCLUSTERED INDEX [IX_Email_EmailAddress] ON [Core].[Email] ([EmailAddress] Asc) 

    Se você usar o GUID como chave primária e criar um índice clusterizado, sugiro usar o valor padrão de NEWSEQUENTIALID () para ele

    Este link diz que melhor do que eu poderia e ajudou na minha tomada de decisão. Eu geralmente opto por um int como uma chave primária, a menos que eu tenha uma necessidade específica de não e também deixo o servidor SQL gerar / manter automaticamente este campo, a menos que eu tenha algum motivo específico para não fazê-lo. Na realidade, as preocupações de desempenho precisam ser determinadas com base no seu aplicativo específico. Há muitos fatores em jogo aqui, incluindo, entre outros, o tamanho esperado do database, a indexação adequada, a consulta eficiente e muito mais. Embora as pessoas possam discordar, acho que em muitos cenários você não notará a diferença com nenhuma das opções e deverá escolher o que é mais apropriado para o aplicativo e o que permite desenvolver mais fácil, rápido e eficazmente (se você nunca concluir o aplicativo Que diferença faz o resto :).

    https://web.archive.org/web/20120812080710/http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html

    PS Não sei por que você usaria um Composite PK ou que benefício você acredita que daria a você.

    Atualmente estou desenvolvendo uma aplicação web com o EF Core e aqui está o padrão que eu uso:

    Todas as minhas classs (tabelas) e um int PK e FK. Eu tenho uma coluna adicional com o tipo Guid (gerado pelo construtor c #) com um índice não clusterizado nele.

    Todas as junções da tabela dentro da EF são gerenciadas através das chaves int, enquanto todo o access de fora (controladores) é feito com os Guids.

    Esta solução permite não mostrar as chaves int em URLs, mas manter o modelo organizado e rápido.