Chaves primárias - teclas nativas, sequência ou GUID?
-
18-09-2019 - |
Pergunta
Em leitura isto e isto e depois lendo isto (Quais referenciam os outros dois ironicamente) Eu me pergunto o tamanho da discussão deste tópico? Eu sou um cara do SQL Server e, portanto, tenho a tendência de usar uma identidade gerada automaticamente na forma de um int. No entanto, quando sei que precisarei de alguma forma de replicação entre servidor e servidor ou sincronização entre cliente e servidor, tendem a usar um GUID como minha chave.
Pergunta: Devo usar um GUID como minha chave primária em todas as tabelas o tempo todo, caso eu precise dessa possível escalabilidade no caminho? Isso torna meu esquema mais flexível, pois pode ser migrado entre plataformas o tempo todo? Isso me ajuda a manter a flexibilidade do meu ORM (independentemente do sabor) por não incorporar recursos específicos da plataforma?
Respostas:
@David Archer: Por seu comentário, atualizei minha postagem para não dizer "chave natural". Você está correto nessa chave natural é definida como tal. Obrigado pela correção.
Solução
Costumo preferir teclas primárias geradas por aplicativos, normalmente usando o algoritmo LO/HI, implementado pelo Nibernate (quando o estou usando em um projeto). Caso contrário, os guids seqüenciais também funcionam. Este não é apenas o meu conselho, mas sim de várias pessoal quem têm Tenho feito toda essa coisa de desenvolvimento há muito mais tempo do que eu.
O problema que vejo com o uso de teclas primárias geradas por DB é que você deve atingir o banco de dados para obter esses valores de identidade em vez de configurar tudo antes de persistir no banco de dados. Normalmente, também quebra a unidade de padrão de trabalho no Nibernate devido a esse fato. Se você não estiver usando o padrão UOW em seu aplicativo, obviamente essa desvantagem não se aplica.
Se você estiver usando o GUIDS para o seu PK, definitivamente deseja usar GUIDs seqüenciais para eliminar a fragmentação do índice. Isso também fornece a "ordem de classificação aproximada" que outro pôster mencionou, embora eu normalmente tenha uma coluna DateInsert ou similar para esses tipos de coisas.
Juntando -se a uma coluna GUID foi mostrado Para ter uma sobrecarga de desempenho bastante mínima versus seu número inteiro de 4 bytes e eu me aventuraria a dizer que, para conjuntos de dados não grandes, a diferença de desempenho é trivial.
As chaves naturais são a desova do diabo. :)
Outras dicas
Você provavelmente não deve usar GUIDs brutos como sua chave primária. Fazer isso leva à fragmentação substancial de seus dados. O SQL Server tem um função Para fornecer um "GUID sequencial" para ajudar a mitigar esse problema. Há uma boa discussão sobre este tópico em profundidade aqui. Outra excelente discussão disso é aqui ...
Isso mostra que a quantidade de fragmentação para GUIDs aleatórios é muito significativa (é recomendado que "a fragmentação em porcentagem" deve estar o mais próximo possível de zero). O número de páginas usadas pelo GUID aleatório é 40% maior e a quantidade de espaço usada em cada página é menor; portanto, o espaço do disco necessário aumentará.
Eu evitaria o GUIDS para chaves primárias, a menos que você saiba que realmente precisará (ou seja, para sincronização multi-sistemas, etc.).
Na terra da replicação do SQL Server, um GUID é adicionado às linhas em tabelas replicadas para alcançar a singularidade, por isso é bem possível estabelecer esse design posteriormente se você tiver a necessidade.
Quanto à fragmentação, considere também o custo do seu espaço em disco. Se você vai ter menos de 10.000 linhas (em uma tabela), provavelmente não é um problema enorme, mas se o seu sistema precisar suportar acima de 10.000 linhas (em uma tabela), você encontrará desempenho e custo de armazenamento em disco (e fragmentação de índice) é melhor servido pelo uso de grandes ints (números inteiros grandes) + identidade (número automático) que escalam bem para o volume.
Eu evitaria as chaves naturais completamente - mesmo o risco de mudar a lógica em torno delas torna IMHO muito arriscado (por exemplo, se eles se tornarem de repente não unique).
Apoio a maioria das outras respostas ao dizer que você deve evitar o GUIDS como sua chave em cluster no SQL Server - se você realmente deseja, você pode usá -los como chave primária, mas não agrupe sua tabela.
A chave primária é o conceito lógico de uma chave para identificar exclusivamente cada linha - aqui, um GUID pode fazer sentido, pois é praticamente garantido ser único.
Mas a chave em cluster é um conceito físico que ordena fisicamente as linhas da tabela e aqui devido à sua natureza aleatória, os guids são mal adequados. Isso levará à fragmentação maciça do índice e, portanto, ao mau desempenho, mesmo se você continuar reorganizando seu índice (e, portanto, os dados da tabela) repetidamente.
Além disso, como a chave de índice em cluster está sendo usada como o valor da pesquisa para encontrar a linha na tabela, ela será adicionada a cada entrada de todo e qualquer índice não agrupado em sua tabela, e aqui o tamanho de O GUID (16 bytes) vs. Int (4 bytes) entra em jogo - você potencialmente desperdiça muito espaço apenas para acompanhar os valores de pesquisa.
A melhor discussão sobre índices e guids primários / agrupados que conheço é o casal de Kim Tripp, a rainha da indexação no SQL Server Land - confira!
- Guid como chave primária
- O debate do índice em cluster continua ...
- Índice em cluster cada vez maior ... de novo!
Seus requisitos finais para um índice em cluster são: pequeno, estável, único e esperançosamente cada vez maior. GUID viola dois deles (pequeno e cada vez maior). Mesmo os GUIDs gerados pela função NewsequencialGuid () no SQL Server não são totalmente e verdadeiramente seqüenciais - então eu também não os usaria.
Marc
Fui queimado muitas vezes por "chaves naturais" mudando ou sendo duplicado para considerá -las usá -las. Minha decisão de usar sequências ou guids para chaves é determinada se espero ler ou falar um deles.
Não tive muita experiência com isso, mas usar um GUIDS para entrar me faz estremecer. 4 bytes versus 36 parece nojento.
No entanto, comecei a usar o GUIDS como identificadores públicos, e não os próprios campos de identidade. Dê uma olhada no URL acima, 1156712. Se, por algum motivo Google Stats também. Considerando que, se a maneira como todos os elementos fosse identificados publicamente foi através do uso de um GUID e as junções internas usavam os campos int ou bigint, você poderia ter o melhor dos dois mundos.
As mescladas ainda são possíveis também usando essa abordagem. Se um conflito for encontrado, um novo identificador interno poderá ser gerado em tempo real sem interromper o restante do aplicativo.