Sobre usar PostgreSQL e UUID como chave primária
(maciejwalkowiak.com)- UUID é frequentemente usado como chave primária de tabelas de banco de dados
- É fácil de gerar, fácil de compartilhar entre sistemas distribuídos e garante unicidade
- Considerando o tamanho do UUID, pode surgir a dúvida se essa é a escolha certa, mas muitas vezes não temos como decidir isso
- Este texto não foca em "UUID é um formato adequado para chave?", e sim em como usar UUID com eficiência como chave primária no PostgreSQL
Usando PostgreSQL e UUID como chave primária
- O que é UUID?
- UUID é frequentemente usado como chave primária de tabelas de banco de dados
- Pode ser compartilhado facilmente entre sistemas distribuídos e garante unicidade
- Por causa do tamanho do UUID, pode haver dúvidas sobre sua adequação, mas muitas vezes não há alternativa de escolha
Tipo de dado UUID no PostgreSQL
-
Armazenar UUID como string
- O PostgreSQL oferece o tipo de dado
textpara armazenar strings - Porém, o tipo
textnão é adequado para armazenar UUID - O PostgreSQL oferece o tipo de dado dedicado
uuidpara UUID - O tipo
uuidé um tipo de dado de 128 bits, e requer 16 bytes para armazenar um valor - O tipo
textadiciona um overhead de 1 ou 4 bytes
- O PostgreSQL oferece o tipo de dado
-
Resultados do experimento
- Foram criadas duas tabelas para comparação: uma com tipo
texte outra com tipouuid - Após inserir 10.000.000 de linhas, foram comparados o tamanho da tabela e o tamanho do índice
- A tabela que usa o tipo
textficou 54% maior, e o tamanho do índice ficou 85% maior
- Foram criadas duas tabelas para comparação: uma com tipo
UUID e índices B-Tree
-
Índices B-Tree e UUID
- UUID aleatório não é adequado para índices B-Tree
- Índices B-Tree funcionam bem com valores ordenados
UUID.randomUUID()do Java retorna UUID v4, que é um valor pseudoaleatório- UUID v7 gera valores ordenados no tempo, sendo mais adequado para índices B-Tree
-
Uso de UUID v7
- Para usar UUID v7 em Java, é necessária a biblioteca
java-uuid-generator - Gerar UUID v7 pode melhorar o desempenho de inserção
- Para usar UUID v7 em Java, é necessária a biblioteca
Impacto do UUID v7 no desempenho de INSERT
- Experimento
- Foi criada uma tabela usando UUID v7, e o desempenho foi medido inserindo 10.000 linhas 10 vezes
- Os resultados são um tanto aleatórios, mas inserir UUID v7 é cerca de 2 vezes mais rápido
Leitura adicional
- Há possibilidade de o PostgreSQL 17 oferecer suporte nativo a UUID v7
- Informações sobre o formato UUID v7
- Impacto do UUID no desempenho como chave primária de banco de dados
Resumo
-
Problema do tamanho do UUID
- Mesmo com otimizações, UUID não é o tipo ideal como chave primária
- Se houver liberdade de escolha, vale considerar outras opções, como TSID
-
Necessidade de otimização
- Se forem esperados grandes volumes de dados ou alto tráfego, é preciso considerar otimização
- Alterar a chave primária é uma tarefa difícil, então é importante definir isso corretamente desde o início
-
Observações
- O autor não é especialista em PostgreSQL, e está apenas compartilhando o que aprendeu
- Se isso foi útil, ele pede feedback por comentários ou pelo Twitter
Resumo do GN⁺
- Este texto trata de maneiras eficientes de usar UUID como chave primária no PostgreSQL
- Mostra por meio de experimento que usar UUID v7 pode melhorar o desempenho de inserção
- Se forem esperados grandes volumes de dados ou alto tráfego, é necessário considerar otimização
- Também vale considerar outras opções, como TSID
4 comentários
Será que é pedir demais querer codificação em base62 para UUID, em vez do formato padrão (hexadecimal + hífens)?
uuidv7 é imbatível
uuidv8+ é um "deus"
O maior obstáculo é que não é amigável para humanos... Eu ainda sinto falta disso em muitos aspectos...
Comentários do Hacker News
Recomenda-se usar
bigserialcomo chave primária amigável a B-tree e considerar UUID codificado como string como opção de localizador de registro externohashids; não tem qualidade criptográfica e não é familiar para pessoas comunsAo projetar o esquema de um banco de dados, tenha em mente os princípios de separação de interesses e afinidade mecânica
Os IDs aleatórios tipados da Stripe na verdade não são aleatórios
bigserial+HMACcriptografados com AES e codificados em base58No Postgres, UUIDs aleatórios não são um grande problema
serial(4 bytes) oubigserial(8 bytes), mas isso não é um grande problema no nível da tabela inteiraAntes de considerar
serialvs. UUID aleatório vs. UUID ordenado no Postgres, há muitas outras coisas com que se preocuparRecentemente escolhi ULID como PK no Postgres e este artigo ajudou bastante: https://brandur.org/nanoglyphs/026-ids
A preferência por ULID vem do fato de ele ser compatível com o tipo UUID e ter timestamp embutido, então ao ordenar pelos IDs eles ficam em ordem de timestamp
Seria bom incluir
int64na comparação para avaliar a sobrecarga de UUIDs em relação à abordagem tradicionalDesempenho de inserção é uma forma ruim de avaliar desempenho
No SQLite, UUID4 é preferido porque há menos chance de colisão no cache de páginas durante o bloqueio de transações
Prefiro chaves primárias inteiras com incremento automático
O benchmark de tempo de inserção do UUIDv7 inclui o tempo de geração do UUID
É improvável que o PostgreSQL 17 inclua suporte a UUIDv7
Comecei a usar
python-ulid, e ULID é superior ao UUIDComo o link do padrão UUID v7 está desatualizado, consulte a RFC 9562: https://datatracker.ietf.org/doc/html/rfc9562