Guid vs INT - Qual é melhor como chave primária?

97

Eu tenho lido sobre razões para usar ou não Guide int.

inté menor, mais rápido, fácil de lembrar, mantém uma sequência cronológica. E quanto a Guid, a única vantagem que encontrei é que é único. Nesse caso, a Guidseria melhor do que inte por quê?

Pelo que vi, intnão tem falhas, exceto pelo limite de número, que em muitos casos é irrelevante.

Por que exatamente foi Guidcriado? Na verdade, acho que ele tem outro propósito além de servir como chave primária de uma tabela simples. (Algum exemplo de um aplicativo real usando Guidalgo?)

(Guid = UniqueIdentifier) ​​no SQL Server

BrunoLM
fonte
1
Em vez de chave primária , acho que você quer dizer chave substituta, ou seja, uma chave que não é a chave natural (a última sendo a chave que usamos no mundo real). Possivelmente você quer dizer índice agrupado.
precisa saber é o seguinte
Lembre-se também da diferença entre KEY (Primária) e INDEX.
Allan S. Hansen
1
Também discutido no SO: stackoverflow.com/questions/11033435/…
Jon of All Trades
2
" intnão tem falhas, exceto pelo limite de número, que em muitos casos é irrelevante.": na verdade, nesse contexto de INT vs GUID, o limite superior de um assinado de 32 bits INTé totalmente irrelevante, pois o limite superior de um sinal assinado , 64 bits BIGINTestá muito além de quase todos os usos (ainda mais se você começar a numerar no limite inferior; e o mesmo vale para INT) e ainda tem a metade do tamanho de um GUID (8 bytes em vez de 16) e seqüencial.
Solomon Rutzky

Respostas:

89

Isso foi solicitado no Stack Overflow aqui e aqui .

A publicação de Jeff explica muito sobre os prós e os contras do uso do GUID.

Profissionais GUID

  • Exclusivo em todas as tabelas, bancos de dados e servidores
  • Permite mesclar facilmente registros de diferentes bancos de dados
  • Permite fácil distribuição de bancos de dados entre vários servidores
  • Você pode gerar IDs em qualquer lugar, em vez de precisar ir até o banco de dados
  • A maioria dos cenários de replicação requer colunas GUID de qualquer maneira

Contras do GUID

  • É impressionantemente 4 vezes maior que o valor tradicional do índice de 4 bytes; isso pode ter implicações sérias de desempenho e armazenamento, se você não tomar cuidado
  • Pesado para depurar ( where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • Os GUIDs gerados devem ser parcialmente seqüenciais para obter o melhor desempenho (por exemplo, newsequentialid()no SQL Server 2005+) e para permitir o uso de índices em cluster

Se você tem certeza sobre o desempenho e não planeja replicar ou mesclar registros, use inte defina o incremento automático ( semente de identidade no SQL Server ).

CoderHawk
fonte
20
Outro golpe da abordagem GUID é que você não pode usá-lo como um identificador para o usuário final. Você realmente espera que seus usuários avisem por telefone que eles têm um problema com o pedido "BAE7DF4-DDF-3RG-5TY3E3RF456AS10"? :)
Brann
3
Se você não usar guias seqüenciais e sua chave primária estiver em cluster (o padrão do SQL Server), todas as inserções de dados serão espalhadas aleatoriamente por toda a tabela, levando à fragmentação maciça de seus dados. Isso pressupõe que os dados seriam normalmente inseridos em algum tipo de ordem, como cronológica.
datagod
6
Guias seqüenciais são apenas seqüenciais até que a instância SQL seja reiniciada. É provável que o primeiro valor seja mais baixo que o anterior, devido à maneira como o valor raiz é gerado, causando todos os tipos de problemas novamente.
mrdenny
20
@Brann Idealmente, você não receberia seus valores de PK para os usuários finais. Eu sei que é algo comum fazê-lo, e é algo que eu mesmo fiz no passado antes de aprender a não fazê-lo. Mas como isso não deve ser feito, esse motivo específico para preferir o INT ao GUID não é válido.
Solomon Rutzky
2
@ChadKuehn Escolhendo UNIQUEIDENTIFIERmais INTporque INTtem um limite superior é bastante pobre raciocínio desde que seja ilimitado, enquanto bem verdade, não é uma prática benefício. Você pode dobrar facilmente a capacidade efetiva de um INTiniciando-o no limite inferior (-2,14 bilhões) em vez de em 1. Ou, se os 4,3 bilhões completos não forem suficientes, comece com um BIGINTque ainda tem apenas 8 bytes, comparado a 16 para o GUID e é seqeuential.
Solomon Rutzky
18

Se você estiver sincronizando seus dados com uma fonte externa, um GUID persistente pode ser muito melhor. Um exemplo rápido de onde estamos usando um GUIDs é uma ferramenta que é enviada ao cliente para rastrear sua rede e fazer certas classes de descoberta automática, armazenar os registros encontrados e, em seguida, todos os registros do cliente são integrados a um banco de dados central de volta ao nosso fim. Se usássemos um número inteiro, teríamos 7.398 "1" s, e seria muito mais difícil acompanhar qual "1" era qual.

TML
fonte
3
Os GUIDs são definitivamente bons como identificadores externos, e eu manteria um índice não agrupado como a "chave externa" ainda manteria um int como a "chave interna", que é a base para o índice clusterizado e as relações de chave estrangeira. Se algo ultrapassar um limite arquitetural (por exemplo, comunicar-se com outro aplicativo), eu aprecio ter algo que não possa ser misturado.
Greg
15

Eu usei uma abordagem híbrida com sucesso. As tabelas contêm AMBOS uma idcoluna inteira de chave primária de incremento automático E uma guidcoluna. Ele guidpode ser usado conforme necessário para identificar globalmente a linha de maneira exclusiva e idpode ser usado para consultas, classificação e identificação humana da linha.

rmirabelle
fonte
3
Que valor o GUID atribui se o idjá é suficiente para os humanos identificarem uma linha?
Martin Smith
6
O ID identifica a linha nesta tabela. O GUID (pelo menos em teoria) identifica essa linha em qualquer lugar do universo conhecido. No meu projeto, os celulares Android têm uma cópia estruturalmente idêntica da tabela em um banco de dados SQLite local. A linha e seu GUID são gerados no Android. Em seguida, quando o Android é sincronizado com o banco de dados back-end, sua linha local é gravada na tabela de back-end sem medo de entrar em conflito com as linhas criadas a partir de qualquer outro dispositivo móvel Android.
precisa
2
@ MartinSmith Eu mesmo usei essa abordagem e funciona muito bem. O GUID é apenas uma chave alternativa, com um índice Não Clusterizado, e é passado do aplicativo, mas reside apenas na tabela principal. Todas as tabelas relacionadas são relacionadas via INTPK. Acho estranho que essa abordagem não seja muito mais comum, pois é o melhor dos dois mundos. Parece que a maioria das pessoas prefere resolver problemas em termos muito absolutistas, sem perceber que o PK não precisa ser um GUID para que o aplicativo ainda use GUIDs para exclusividade e / ou portabilidade global.
Solomon Rutzky
1
@rmirabelle Eu pensei sobre essa abordagem e estava hesitando, mas sua resposta me convenceu. Basicamente, estou em uma situação em que preciso ter um identificador exclusivo para um item de trabalho (que pode ser acessado pela rede de qualquer lugar), mas não quero fazer uma ida e volta ao banco de dados primeiro. GUIDs são uma boa solução para isso, mas imagino que JOINs se tornará muito mais lento se eu não tiver uma chave em cluster seqüencial.
easuter 31/10/2015
1
@easuter Concordo em não adicionar os campos de identificação "apenas por uma questão de segurança", como nas tabelas "ponte" muitos para muitos, nas quais o PK deve ser um composto dos dois FKs que estão sendo relacionados. Mas aqui não é uma troca, uma vez que o campo ID não é meramente por sua causa. Permitir que o sistema funcione com eficiência é bastante importante ;-). E, eu argumentaria que, no seu caso, como os GUIDs são gerados externamente, eles não têm garantia exclusiva, mesmo que sejam pragmáticos. Mas a responsabilidade pela integridade dos dados é motivo suficiente para ter GUID ser uma chave alternativa e ID ser PK no seu caso :)
Solomon Rutzky
1

Algumas práticas recomendadas ainda mencionam que você deve usar um tipo de dados que acomode com menos memória possível todo o conjunto de valores que você usará. Por exemplo, se você o está usando para armazenar um número de empregadores em uma pequena empresa e é improvável que chegue a 100, ninguém sugeriria o uso de um valor bigint, enquanto o int (mesmo o smallint) faria.

Obviamente, a desvantagem disso é como "Diga não à escalabilidade!"


Além disso, eu sei que isso não está totalmente relacionado, mas há outro fator a respeito disso. Quando não é excessivo, geralmente tento recomendar o uso de uma chave primária não gerada automaticamente, se isso fizer sentido. Por exemplo, se você estiver salvando as informações do motorista, não se preocupe em criar uma nova coluna gerada automaticamente para "ID", basta usar o número da licença.

Eu sei que isso parece realmente óbvio, mas vejo isso sendo esquecido com bastante frequência.

Para contexto: esta parte da resposta foi abordada a partir de uma abordagem teórica de dados, na qual você deseja que seu PK seja o identificador exclusivo de dados de um registro. Na maioria das vezes, criamos aqueles quando eles já existem, daí a resposta anterior.

No entanto, é muito raro você ter um controle rígido sobre esses pontos de dados e, como tal, pode ser necessário fazer correções ou ajustes. Você não pode fazer isso com chaves primárias (bem, você pode, mas pode ser uma dor).

Obrigado @VahiD pelos esclarecimentos.

Alfa
fonte
o uso de chaves primárias significativas não é recomendado, considere abaixo o cenário, alguém digitou o número de licença errado e você usou esse ID nas tabelas 3-4 como chave estrangeira. Como você corrige esse erro? simplesmente editar o número da licença não seria suficiente neste caso.
VahiD 07/10/2015
1
Engraçado: li o seu comentário e pensei "sim, é claro", depois voltei a ler minha resposta e pensei "eu disse isso"? Engraçado como as coisas mudam em alguns anos. Provavelmente, eu vinha de uma base mais teórica, mas, a menos que você tenha um controle rígido (raramente), isso não trará muitos benefícios. Vou atualizar a resposta.
Alpha
upvote para o desenvolvimento nos anos :)
Vahid
1

O uso de IDs de incremento automático pode vazar informações sobre sua atividade comercial. Se você administra uma loja e usa order_idpara identificar publicamente uma compra, qualquer pessoa pode descobrir seu número mensal de vendas por aritmética simples.

golopot
fonte
0

Outra coisa com como os GUIDs são gerados. mrdenny apontou corretamente que, mesmo que newsequentialid () esteja sendo usado, reiniciar as instâncias faz com que novos valores iniciem com os "buracos" deixados para trás no processamento anterior. Outra coisa que afeta os GUIDs "sequenciais" é a placa de rede. Se bem me lembro, o UID da NIC é usado como parte do algoritmo GUID. Se uma NIC for substituída, não há garantia de que o UID terá um valor mais alto para manter o aspecto seqüencial das coisas. Também não tenho certeza de como várias NICs podem afetar a atribuição de valores usando o algoritmo.

Apenas um pensamento e espero estar me lembrando corretamente. Tenha um ótimo dia!

bobo8734
fonte
2
Bem-vindo aos administradores de banco de dados, bobo8734. Você poderia encontrar algumas fontes para esses comentários? Se você não tiver certeza deles, talvez eles sejam mais úteis como um comentário (quando você tem o representante) do que uma resposta independente.
LowlyDBA
-6

Use ambos

Use int / Bigint para Chave Primária, pois é fácil manter e usar como relações de chave estrangeira.

Mas vincule uma coluna ao GUID para que cada linha também tenha uma coluna exclusiva

Abdul Hannan Ijaz
fonte
2
Explicar o seu raciocínio por trás dessa sugestão não faria mal a ninguém, tenho certeza.
Andriy M
GUID é de 36 caracteres longa será difícil de ler no caso de você estiver procurando por um caso específico ..
Abdul Hannan Ijaz
1
Tudo bem, mas isso realmente não explica por que o OP deve usar os dois inte guid, como você sugere na sua resposta. Além disso, eu não estava falando sobre explicar sua sugestão apenas para mim - meu argumento era que você poderia querer atualizar sua resposta . A propósito, você sabe que outro respondente já sugeriu o mesmo (mais ou menos) que você ?
Andriy M
Yup eu quis dizer a mesma coisa .. arrefecer BTW :)
Abdul Hannan Ijaz