Qual sua opinião sobre o uso de UUIDs como identificadores de linha de banco de dados, principalmente em aplicativos da web?

StackOverflow https://stackoverflow.com/questions/5949

  •  08-06-2019
  •  | 
  •  

Pergunta

Sempre preferi usar números inteiros longos como chaves primárias em bancos de dados, por simplicidade e velocidade (suposta).Mas ao usar um DESCANSAR ou esquema de URL semelhante ao Rails para instâncias de objetos, eu acabaria com URLs como este:

http://example.com/user/783

E então a suposição é que também existem usuários com IDs 782, 781, ..., 2 e 1.Supondo que o aplicativo da web em questão seja seguro o suficiente para impedir que pessoas insiram outros números para visualizar outros usuários sem autorização, uma chave substituta simples atribuída sequencialmente também "vaza" o número total de instâncias (mais antigas que esta), neste caso usuários , que podem ser informações privilegiadas.(Por exemplo, sou o usuário nº 726 no stackoverflow.)

Será que um UUID/GUID é uma solução melhor?Então eu poderia configurar URLs como este:

http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66

Não é exatamente sucinto, mas há menos informações implícitas sobre os usuários em exibição.Claro, isso cheira a “segurança através da obscuridade”, o que não substitui a segurança adequada, mas parece pelo menos um pouco mais seguro.

Esse benefício compensa o custo e a complexidade da implementação de UUIDs para instâncias de objetos endereçáveis ​​pela web?Acho que ainda gostaria de usar colunas inteiras como PKs de banco de dados apenas para acelerar as junções.

Há também a questão da representação de UUIDs no banco de dados.Eu sei que o MySQL os armazena como strings de 36 caracteres.O Postgres parece ter uma representação interna mais eficiente (128 bits?), Mas eu ainda não tentei.Alguém tem alguma experiência com isso?


Atualizar:para aqueles que perguntaram sobre usar apenas o nome de usuário no URL (por exemplo, http://example.com/user/yukondude), que funciona bem para instâncias de objetos com nomes exclusivos, mas e quanto aos zilhões de objetos de aplicativos da web que só podem ser identificados por número?Pedidos, transações, faturas, nomes de imagens duplicados, perguntas sobre stackoverflow, ...

Foi útil?

Solução

Não posso dizer sobre o lado web da sua pergunta.Mas os uuids são ótimos para aplicativos de n camadas.A geração de PK pode ser descentralizada:cada cliente gera seu próprio pacote sem risco de colisão.E a diferença de velocidade geralmente é pequena.

Certifique-se de que seu banco de dados suporte um tipo de dados de armazenamento eficiente (16 bytes, 128 bits).No mínimo você pode codificar a string uuid em base64 e usar char(22).

Eu os usei extensivamente com o Firebird e recomendo.

Outras dicas

Pelo que vale a pena, vi um procedimento armazenado de longa execução (mais de 9 segundos) cair para apenas algumas centenas de milissegundos de tempo de execução simplesmente mudando de chaves primárias GUID para números inteiros.Isso não quer dizer exibindo um GUID é uma má ideia, mas como outros apontaram, juntá-los e indexá-los, por definição, não será tão rápido quanto com números inteiros.

Posso responder que no servidor SQL, se você usar um tipo de dados identificador exclusivo (GUID) e usar a função NEWID() para criar valores, obterá uma fragmentação horrível devido a divisões de páginas.A razão é que ao usar NEWID() o valor gerado não é sequencial.O SQL 2005 adicionou a função NEWSEQUANTIAL() para remediar isso

Uma maneira de ainda usar GUID e int é ter um guid e um int em uma tabela para que o guid seja mapeado para o int.o guid é usado externamente, mas o int internamente no banco de dados

por exemplo

457180FB-C2EA-48DF-8BEF-458573DA1C10    1
9A70FF3C-B7DA-4593-93AE-4A8945943C8A    2

1 e 2 serão usados ​​em junções e nos guias do aplicativo web.Esta tabela será bem estreita e deverá ser bem rápida de consultar

Por que combinar sua chave primária com seu URI?

Por que não fazer com que sua chave URI seja legível por humanos (ou imprevisível, dependendo de suas necessidades) e que seu índice primário seja baseado em número inteiro, para que você obtenha o melhor dos dois mundos.Muitos softwares de blog fazem isso, onde o ID exposto da entrada é identificado por um 'slug' e o ID numérico fica oculto dentro do sistema.

O benefício adicional aqui é que agora você tem uma estrutura de URL muito boa, o que é bom para SEO.Obviamente, para uma transação isso não é bom, mas para algo como stackoverflow, é importante (veja URL no topo...).Obter exclusividade não é tão difícil.Se você estiver realmente preocupado, armazene um hash do slug dentro de uma tabela em algum lugar e faça uma pesquisa antes de inserir.

editar: Stackoverflow não usa exatamente o sistema que descrevo, veja o comentário de Guy abaixo.

Em vez de URLs como este:

http://example.com/user/783

Por que não ter:

http://example.com/user/yukondude

Qual é mais amigável para os humanos e não vaza essa mínima informação?

Você pode usar um número inteiro relacionado ao número da linha, mas não sequencial.Por exemplo, você poderia pegar os 32 bits do ID sequencial e reorganizá-los com um esquema fixo (por exemplo, o bit 1 se torna o bit 6, o bit 2 se torna o bit 15, etc.).
Esta será uma criptografia bidirecional e você terá certeza de que dois IDs diferentes sempre terão criptografias diferentes.
Obviamente, seria fácil de decodificar, se alguém gastasse tempo para gerar IDs suficientes e obter o esquema, mas, se entendi corretamente o seu problema, você só quer não fornecer informações com muita facilidade.

Usamos GUIDs como chaves primárias para todas as nossas tabelas, pois ele também funciona como RowGUID para replicação do MS SQL Server.Facilita muito quando o cliente abre repentinamente um escritório em outra parte do mundo...

Não acho que um GUID ofereça muitos benefícios.Os usuários odeiam URLs longos e incompreensíveis.

Crie um ID mais curto que você possa mapear para o URL ou aplique uma convenção de nome de usuário exclusiva (http://example.com/user/brianly).Os caras do 37Sinais provavelmente zombaria de você por se preocupar com algo assim quando se trata de um aplicativo da web.

Aliás, você pode forçar seu banco de dados a começar a criar IDs inteiros a partir de um valor base.

Também depende do que você preocupa em sua aplicação.Para aplicativos de n camadas, GUIDs/UUIDs são mais simples de implementar e mais fáceis de portar entre bancos de dados diferentes.Para produzir chaves inteiras, alguns bancos de dados suportam nativamente um objeto de sequência e alguns requerem a construção personalizada de uma tabela de sequência.

Provavelmente, as chaves inteiras (não tenho números) fornecem uma vantagem para o desempenho de consulta e indexação, bem como para o uso de espaço.A consulta direta ao banco de dados também é muito mais fácil usando teclas numéricas, menos copiar/colar, pois são mais fáceis de lembrar.

Eu trabalho com um sistema de gerenciamento de alunos que usa UUIDs na forma de um número inteiro.Eles têm uma tabela que contém o próximo ID exclusivo.

Embora esta seja provavelmente uma boa ideia do ponto de vista arquitetônico, torna difícil trabalhar com ela no dia a dia.Às vezes é necessário fazer inserções em massa e ter um UUID torna isso muito difícil, geralmente exigindo a escrita de um cursor em vez de uma simples instrução SELECT INTO.

Eu tentei ambos em aplicativos da web reais.

Minha opinião é que é preferível usar números inteiros e ter URLs curtas e compreensíveis.

Como desenvolvedor, é um pouco horrível ver números inteiros sequenciais e saber que algumas informações sobre a contagem total de registros estão vazando, mas, honestamente, a maioria das pessoas provavelmente não se importa, e essas informações nunca foram realmente críticas para meus negócios.

Ter URLs UUID longos e feios me parece muito mais desagradável para usuários normais.

Penso que esta é uma daquelas questões que provocam debates quase religiosos e é quase inútil falar sobre ela.Eu diria apenas que use o que você preferir.Em 99% dos sistemas não importa que tipo de chave você usa, então os benefícios (declarados nas outras postagens) de usar um tipo em vez de outro nunca serão um problema.

Acho que usar um GUID seria a melhor escolha na sua situação.Ocupa mais espaço, mas é mais seguro.

O Youtube usa 11 caracteres com codificação base64, que oferece 11 ^ 64 possibilidades, e geralmente são bastante fáceis de escrever.Eu me pergunto se isso ofereceria melhor desempenho do que um UUID completo.O UUID convertido para base 64 teria o dobro do tamanho que acredito.

Mais informações podem ser encontradas aqui: https://www.youtube.com/watch?v=gocwRvLhDf8

Contanto que você use um sistema de banco de dados com armazenamento eficiente, o HDD é barato hoje em dia ...

Eu sei que os GUIDs podem ser difíceis de trabalhar algumas vezes e vêm com alguma sobrecarga de consulta, no entanto, do ponto de vista da segurança, eles são um salvador.

Pensando na segurança pela obscuridade, eles se encaixam bem ao formar URIs obscuros e construir bancos de dados normalizados com segurança definida por tabela, registro e coluna. Você não pode errar com GUIDs, tente fazer isso com IDs baseados em números inteiros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top