Eu tenho um aplicativo que usa GUID como chave primária em quase todas as tabelas e li que há problemas sobre o desempenho ao usar GUID como chave primária. Sinceramente, não vi nenhum problema, mas estou prestes a iniciar um novo aplicativo e ainda quero usar os GUIDs como chaves primárias, mas estava pensando em usar uma chave primária composta (o GUID e talvez outro campo .)
Estou usando um GUID porque eles são agradáveis e fáceis de gerenciar quando você tem ambientes diferentes, como bancos de dados de "produção", "teste" e "dev", e também para dados de migração entre bancos de dados.
Usarei o Entity Framework 4.3 e desejo atribuir o Guid no código do aplicativo, antes de inseri-lo no banco de dados. (ou seja, não quero permitir que o SQL gere o Guid).
Qual é a melhor prática para criar chaves primárias baseadas em GUID, a fim de evitar os supostos hits de desempenho associados a essa abordagem?
Respostas:
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
, umaGUID
, 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
ouBIGINT
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 osGUID
- 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 umaGUID
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: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 colunaMYINT
(INT IDENTITY
) como sua chave de cluster - use isto: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!fonte
DATETIME
por exemplo, NÃO são úteis para uma chave de cluster, pois eles têm uma precisão de 3,33ms e, portanto, podem existir duplicatas. Portanto, nesse caso, você * ainda precisa de umINT IDENTITY
- portanto, eu normalmente o uso por padrão, pois desde os meus mais de 20 anos de experiência, uma chave natural realmente utilizável quase nunca existe ...Uso GUIDs como PKs desde 2005. Nesse mundo de banco de dados distribuído, é absolutamente a melhor maneira de mesclar dados distribuídos. Você pode disparar e esquecer mesclar tabelas sem a preocupação de ints correspondentes nas tabelas unidas. As junções de GUIDs podem ser copiadas sem qualquer preocupação.
Esta é minha configuração para usar GUIDs:
PK = GUID. Os GUIDs são indexados de maneira semelhante às seqüências de caracteres, portanto, tabelas de linhas altas (mais de 50 milhões de registros) podem precisar de particionamento de tabelas ou outras técnicas de desempenho. O SQL Server está ficando extremamente eficiente, portanto, as preocupações com o desempenho são cada vez menos aplicáveis.
O PK Guid é um índice NÃO agrupado. Nunca indexe um GUID por cluster, a menos que seja NewSequentialID. Mas, mesmo assim, uma reinicialização do servidor causará grandes interrupções no pedido.
Adicione ClusterID Int a todas as tabelas. Este é o seu Índice CLUSTERED ... que ordena sua mesa.
A associação aos ClusterIDs (int) é mais eficiente, mas eu trabalho com 20 a 30 milhões de tabelas de registros, portanto, a associação aos GUIDs não afeta visivelmente o desempenho. Se você deseja desempenho máximo, use o conceito ClusterID como sua chave primária e participe do ClusterID.
Aqui está a minha tabela de e-mail ...
fonte
Atualmente, estou desenvolvendo um aplicativo Web com o EF Core e aqui está o padrão que eu uso:
Todas as minhas aulas (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.
Todas as junções da tabela no EF são gerenciadas através das teclas int, enquanto todo o acesso de fora (controladores) é feito com os Guids.
Essa solução permite não mostrar as chaves int nos URLs, mas manter o modelo organizado e rápido.
fonte
Se você usar GUID como chave primária e criar um índice clusterizado, sugiro usar o valor padrão NEWSEQUENTIALID () para ele
fonte
Este link diz que é melhor do que eu pude e ajudou na minha tomada de decisão. Normalmente, opto por um int como chave primária, a menos que tenha uma necessidade específica e também permita que o SQL Server gere / mantenha automaticamente esse campo, a menos que tenha algum motivo específico para não fazê-lo. Na realidade, as preocupações com o desempenho precisam ser determinadas com base no seu aplicativo específico. Existem muitos fatores em jogo aqui, incluindo, entre outros, o tamanho esperado do banco de dados, 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á diferença em nenhuma das opções e deve escolher o que é mais apropriado para seu aplicativo e o que permite que você se desenvolva de maneira mais fácil, rápida e eficaz (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 PK composto ou que benefício você acredita que isso lhe daria.
fonte
Na maioria das vezes, não deve ser usada como chave primária de uma tabela porque realmente afeta o desempenho do banco de dados. links úteis sobre o impacto da GUID no desempenho e como chave primária.
fonte
Ter IDs seqüenciais facilita muito para um hacker ou minerador de dados comprometer seu site e dados. Lembre-se disso ao escolher um PK para um site.
fonte