Eu geralmente uso IDs de incremento automático como Chaves Primárias em bancos de dados. Estou tentando aprender os benefícios do uso de GUIDs. Eu li este artigo: https://betterexplained.com/articles/the-quick-guide-to-guids/
Percebo que esses GUIDs são usados para identificar objetos no nível do aplicativo. Eles também são armazenados como a chave primária no nível do banco de dados. Por exemplo, digamos que eu tenha a seguinte classe:
public class Person
{
public GUID ID;
public string Name;
..
//Person Methods follow
}
Digamos que eu queira criar uma nova pessoa na memória e, em seguida, insira a Pessoa em um banco de dados. Posso apenas fazer isso:
Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);
Digamos que eu tivesse um banco de dados contendo milhões e milhões de linhas com um GUID como Chave Primária. Isso sempre será único? Estou entendendo GUIDs corretamente?
Li este artigo anteriormente: http://enterprisecraftsmanship.com/2014/11/15/cqs-with-database-generated-ids/ . Isso me confunde um pouco, pois parece recomendar um meio termo entre GUIDs e números inteiros como Chaves Primárias.
Editar 11/06/18
Eu acredito que os Guids são mais adequados do que ints para minhas necessidades. Atualmente, estou usando mais o CQRS e os GUIDs se encaixam melhor.
Percebo que alguns desenvolvedores modelam os GUIDs como seqüências de caracteres no modelo de domínio, por exemplo, aqui: https://github.com/dotnet-architecture/eShopOnContainers/blob/dev/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/ Buyer.cs - neste caso: IdentityGuid é um GUID modelado como uma sequência. Existe algum motivo para fazer isso além do indicado aqui: Use um objeto de valor personalizado ou um Guid como identificador de entidade em um sistema distribuído? . É "normal" modelar o GUID como uma string ou devo modelá-lo como um GUID no modelo e no banco de dados?
fonte
Respostas:
Os GUIDs são, por definição, "identificadores globalmente exclusivos". Existe um conceito semelhante, mas um pouco diferente em Java, chamado UUIDs "Universally Unique IDentifiers". Os nomes são intercambiáveis para todos os usos práticos.
Os GUIDs são essenciais para o funcionamento da clusterização de bancos de dados pela Microsoft e, se você precisar incorporar dados de fontes às vezes conectadas, eles realmente ajudarão a evitar colisões de dados.
Alguns fatos do Pro-GUID:
Alguma feiura com GUIDs
Os GUIDs aumentarão seus índices; portanto, o custo do espaço em disco da indexação de uma coluna será maior. GUIDs aleatórios fragmentarão seus índices.
Se você sabe que não vai sincronizar dados de redes diferentes, os GUIDs podem ter mais sobrecarga do que valem.
Se você precisar ingerir dados de clientes às vezes conectados, eles podem ser muito mais robustos para evitar colisões de chaves do que depender da definição de intervalos de sequência para esses clientes.
fonte
Sempre? nem sempre; é uma sequência finita de bits.
Milhões e milhões, você provavelmente está seguro. Um milhão de milhões e a probabilidade de uma colisão se torna significativa. Porém, há boas notícias: você já ficou sem espaço em disco no momento em que isso acontece.
Você pode; não é uma ideia totalmente boa. Seu modelo de domínio normalmente não deve gerar números aleatórios; eles devem ser entradas para o seu modelo.
Além disso, quando você estiver lidando com uma rede não confiável, onde poderá receber mensagens duplicadas, um UUID gerado deterministicamente o protegerá de ter entidades duplicadas. Mas se você atribuir um novo número aleatório a cada um, terá mais trabalho a fazer para identificar a duplicação.
Veja a descrição do uuid baseado em nome no RFC 4122
Eu não acho que isso importe muito. Para a maior parte do seu modelo de domínio, é um identificador ; a única consulta que você faz é se é ou não o mesmo que outro identificador. Seu modelo de domínio normalmente não estará olhando para a representação na memória de um identificador.
Se o GUID estiver disponível como um "tipo primitivo" na configuração independente de domínio, eu o usaria; permite que o contexto de suporte escolha otimizações apropriadas que possam estar disponíveis.
O que você deve reconhecer, no entanto, é que a representação do identificador, tanto na memória quanto no armazenamento, é uma decisão que você está tomando em sua implementação e, portanto, deve tomar medidas para garantir que a pegada do código seja acoplada àquela decisão é pequena - veja Parnas 1972 .
fonte
O GUID ou o UUID provavelmente será único devido à forma como são gerados e eles fornecem uma maneira segura de garantir exclusividade sem precisar se comunicar com uma autoridade central.
Benefícios dos GUIDs como chave primária:
No exemplo que você forneceu:
A especificação do GUID antes do tempo de inserção pode salvar uma viagem de ida e volta ao banco de dados ao inserir sucessivos registros filhos e permitir que você os confirme na mesma transação.
Distúrbios nos GUIDs como uma chave primária:
Se o seu aplicativo não precisar de sharding ou clustering, seria melhor usar tipos de dados menores e mais simples, como int ou bigint.
Muitos bancos de dados têm suas próprias implementações internas que tentam atenuar os problemas de armazenamento causados pelos GUIDs e pelo SQL Server, inclusive com uma função newsequentialid para ajudar na ordenação dos UUIDs, permitindo um melhor uso dos índices e geralmente possuem melhores características de desempenho.
Além disso, da perspectiva de um testador, usuário ou desenvolvedor que trabalha com o aplicativo, o uso de um ID em um GUID melhorará significativamente a comunicação. Imagine ter que ler um GUID por telefone.
No final, a menos que um cluster de grande escala ou URLs ofuscantes seja um requisito, é mais pragmático usar IDs de incremento automático.
fonte
Eu diria que não, não use GUIDs como chaves primárias. Atualmente, estou lidando com esse banco de dados e eles são uma das principais causas de problemas de desempenho.
Os 12 bytes extras são adicionados rapidamente; lembre-se, a maioria dos PKs serão FKs em outras tabelas, e apenas três FKs em uma tabela agora têm 48 bytes extras para cada linha. Isso se soma na tabela e nos índices. Ele também é adicionado à E / S do disco. Esses 12 bytes extras precisam ser lidos e gravados.
E se você não estiver usando guias seqüenciais e as PKs estiverem agrupadas (o que acontece por padrão), o SQL precisará, periodicamente, mover páginas inteiras de dados para espremer mais no "local" certo. Para um banco de dados de transações altamente com muitas inserções, atualizações e exclusões, as coisas atolam rapidamente.
Se você precisar de algum tipo de identificador exclusivo para sincronização ou algo assim, adicione uma coluna guid. Apenas não faça o PK.
fonte
Esse é de longe o motivo mais importante para o uso de GUIDs.
O fato de você poder criar um ID exclusivo sem que seu código conheça ou se comunique com a camada de persistência é um grande benefício.
Você pode ter certeza de que o objeto Person que você acabou de gerar em seu servidor, telefone pc, laptop, dispositivo offline ou o que for único em todos os seus servidores em todo o mundo está distribuído.
Você pode colocá-lo em qualquer tipo de banco de dados rdb ou no-sql, arquivo, enviá-lo para qualquer serviço da web ou jogá-lo fora imediatamente como desnecessário
Não, você nunca terá uma colisão.
Sim, as inserções podem ser um pouco mais lentas, pois pode ser necessário mexer no índice.
Sim, é maior que um int.
Sei que muitas pessoas se sentem fortemente com as incidentes automobilísticos e esse é um tópico controverso com os DBAs
Mas eu realmente não posso afirmar com força suficiente como guias superiores são. Você deve usar guias por padrão em qualquer aplicativo.
auto inc ints tem muitas falhas
Você usa um banco de dados distribuído No-Sql. Você simplesmente não pode conversar com todas as outras instâncias para descobrir qual é o próximo número.
Você usa um sistema de fila de mensagens. As coisas precisam de IDs antes de atingirem o banco de dados
Você está criando vários itens e editando-os antes de salvar. Cada um precisa de um ID antes de acessar o banco de dados
Você deseja excluir e reinserir linhas. Certifique-se de não contar seus IDs de auto inc e acabar!
Você deseja não expor quantos pedidos você recebeu este ano a todos os usuários
Você deseja mover dados anônimos da produção para testar e manter os relacionamentos intactos. Mas não exclua todos os dados de teste existentes.
Você deseja mesclar seu produto de inquilino único em um banco de dados multilocatário, mas todos têm um pedido 56.
Você cria objetos que são persistentes, mas efêmeros. (pedidos incompletos) novamente, não use todas as suas entradas com coisas que não existem mais.
A lista é interminável e todos são problemas reais que acontecem com as pessoas o tempo todo. diferente de ficar sem espaço em disco por causa de colunas FK um pouco maiores
Finalmente, o grande problema com as ints é que você as esgotou !!! ok, em teoria, você não tem, há um monte. Mas, na prática, você o faz porque as pessoas não os tratam como números aleatórios sem significado. eles fazem coisas como
ah, não quero que os clientes pensem que somos novos. começar às 10.000
Eu tive que importar uma carga de dados, então eu apenas subi a semente para 1m para sabermos o que é importado
precisamos de categorias de dados. todo período começa no próximo milhão, para que possamos usar os primeiros dígitos como um número mágico
Excluí e reimportei todos os dados novamente com novos IDs. Sim, mesmo os logs de auditoria.
use esse número, que é uma chave composta, como o ID dessa outra coisa
fonte
É aí que você deve parar, ali mesmo, e repensar.
A chave primária do banco de dados NUNCA deve ter significado comercial. Deve ser sem sentido por definição.
Portanto, adicione o GUID como sua chave comercial e uma chave primária normal (geralmente uma longa int) como chave primária do banco de dados. Você sempre pode colocar um índice exclusivo no GUID para garantir a exclusividade.
Isso está falando da teoria do banco de dados, é claro, mas também é uma boa prática. Eu lidei com bancos de dados em que as chaves primárias tinham significado comercial (um cliente pensou em economizar alguns recursos do banco de dados usando-os como números de funcionários, números de clientes, etc. etc., por exemplo) e isso sempre gera problemas.
fonte
Sempre use chaves primárias (PKs) com incremento automático de banco de dados.
Por que usar o incremento automático em vez do GUID / UUID?
Mas como lidar com cacos, cachos, etc.?
Uma PK de 3 colunas para uma tabela em cluster pode ser ...
Mas e quanto ...?
Várias viagens ao banco de dados - a maioria dos aplicativos não precisa identificar exclusivamente um registro que está sendo criado até que ele seja inserido no banco de dados desde o encadeamento / sessão / o que estiver funcionando apenas um por vez. Se o aplicativo realmente precisar dessa capacidade, use um PK temporário gerado pelo aplicativo que não seja enviado ao banco de dados . Deixe o banco de dados colocar seu próprio PK de incremento automático na linha quando for inserido. As inserções usarão a PK temporária, enquanto as atualizações e exclusões usarão a PK permanente atribuída pelo banco de dados.
Desempenho - Os computadores podem processar números inteiros simples muito mais rapidamente do que qualquer outra coisa, devido ao valor muito maior do domínio, se possível, por elemento em um GUID (37) versus um número inteiro (10). Lembre-se também de que cada caractere em um GUID deve primeiro ser convertido em um número a ser manipulado pela CPU.
Os usos indevidos comuns de chaves primárias PKs têm apenas um objetivo ... identificar absolutamente exclusivamente uma linha em uma tabela. Qualquer outra coisa é um mau uso muito comum.
Detectando registros ausentes
Classificação
fonte
Como qualquer coisa, há vantagens e desvantagens em fazer isso:
O bom:
Suas chaves têm sempre o mesmo comprimento (bancos de dados muito grandes podem ter chaves muito grandes)
A exclusividade é praticamente garantida - mesmo quando você as está gerando em um sistema separado e / ou não leu o último ID do banco de dados
O mal:
Como mencionado muito acima - índices maiores e armazenamento de dados.
Você não pode solicitar por ID, mas por outra coisa. Mais índices, provavelmente menos eficientes.
Eles são menos legíveis por humanos. Inteiros geralmente são mais fáceis de analisar, lembrar e digitar para as pessoas. Usar GUIDs como IDs nas cláusulas WHERE em várias tabelas unidas pode fazer sua cabeça derreter.
Como tudo, use-os quando apropriado, não seja dogmático - em muitas situações, números inteiros com auto-incremento são melhores, às vezes os GUIDs são ótimos.
fonte
Sim, você pode usar o GUID como chave primária. O lado negativo é o tamanho e a rápida fragmentação do índice.
A menos que você precise de exclusividade nos bancos de dados (por exemplo, um cluster), é preferível um número inteiro.
fonte
Aqui está minha opinião sobre esse problema - a solução é uma casa intermediária entre os valores GUID e int, aproveitando o melhor de ambos.
A classe gera um valor de ID pseudo-aleatório (mas aumentando ao longo do tempo), que é semelhante a um GUID Comb .
A principal vantagem é que ele permite que os valores de ID sejam gerados no cliente, em vez de usar valores de incremento automático gerados no servidor (o que requer uma ida e volta) com risco quase zero de valores duplicados.
Os valores gerados usam apenas 8 bytes em vez de 16 para um GUID e não dependem de uma ordem de classificação de banco de dados específica (por exemplo, Sql Server for GUIDs ). Os valores podem ser expandidos para usar todo o longo período não assinado, mas isso causaria problemas em qualquer banco de dados ou outro repositório de dados que possuísse apenas tipos de números inteiros assinados.
fonte