Diferencas entre UUID v4 (aleatório) e v7 (ordenado por tempo). Estrutura de bits, impacto em desempenho B-tree, comparação com ULID e casos de uso.
Tanto UUID v4 quanto v7 são identificadores de 128 bits formatados como 32 caracteres hexadecimais agrupados como 8-4-4-4-12. A diferença esta no conteudo desses bits.
Um UUID v4 se parece com:
f47ac10b-58cc-4372-a567-0e02b2c3d479
^^^^
nibble de versão = 4
Um UUID v7 se parece com:
018e2b3c-d4a1-7f2e-b8c9-1234567890ab
^^^^^^^^^^^^^
48 bits timestamp ms
^
nibble de versão = 7
Esta diferença estrutural tem implicações reais de desempenho para bancos de dados.
UUID v4 aloca 122 bits para aleatoriedade. Os 6 bits restantes são reservados:
0100 = 4)10 para RFC 4122)xxxxxxxx-xxxx-4xxx-[89ab]xxx-xxxxxxxxxxxx
Os caracteres x são aleatórios. O 13o caractere e sempre 4. O 17o caractere e sempre um de 8, 9, a ou b.
Geração na maioria das linguagens é uma única chamada:
import uuid
str(uuid.uuid4())
# 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
crypto.randomUUID() // nativo desde Node 14.17 / todos os navegadores modernos
# 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
import "github.com/google/uuid"
uuid.New().String()
UUID v7, padronizado no RFC 9562 (maio de 2024), usa os primeiros 48 bits para um timestamp Unix em milissegundos, seguido por bits de versão e dados aleatórios:
[48 bits timestamp ms][4 bits versão = 7][12 bits aleatórios][2 bits variante][62 bits aleatórios]
O prefixo de timestamp de 48 bits significa que UUIDs gerados no mesmo milissegundo são quase identicos em seus bits mais significativos, e UUIDs gerados posteriormente são lexicograficamente maiores. Esta é a propriedade que torna o v7 amigável para índices B-tree.
# Python 3.11+ tem uuid7 nativo na biblioteca padrão
import uuid
str(uuid.uuid7()) # Python 3.11+
// Nenhum suporte nativo ainda, use uma biblioteca
import { v7 as uuidv7 } from 'uuid';
uuidv7()
// '018e2b3c-d4a1-7f2e-b8c9-1234567890ab'
// Java não tem UUID v7 nativo, use java-uuid-generator
import com.fasterxml.uuid.Generators;
Generators.timeBasedEpochRandomGenerator().generate().toString();
Indices B-tree (usados por PostgreSQL, MySQL, SQL Server é a maioria dos outros) mantem ordem sequencial. Quando você insere uma nova linha, o banco de dados encontra onde a nova chave pertence no índice ordenado é a coloca la.
Com UUID v4, novas chaves são distribuidas uniformemente ao acaso em todo o espaco de 128 bits. A nova chave quase nunca pertence ao final do índice. O banco de dados deve:
Em altas taxas de inserção, isso causa divisões constantes de página, alta amplificação de escrita e baixa utilização de cache. Paginas de índice são removidas do pool de buffer assim que são escritas porque novas inserções quase nunca tocam a mesma página duas vezes.
Com UUID v7, novas chaves são sempre maiores que todas as chaves anteriores (dentro do mesmo milissegundo). As inserções vão para a página folha mais a direita da B-tree. As páginas são preenchidas sequencialmente, as divisões são raras e as páginas ativas permanecem no pool de buffer.
A diferença e mensuravel. Benchmarks no PostgreSQL com chaves primárias UUID v4 vs. v7 tipicamente mostram 20 a 50% melhor rendimento de inserção para v7 em tabelas grandes, com inchaco de índice significativamente menor.
Use UUID v4 quando:
Use UUID v7 quando:
ULID (Identificador Universal Unico Lexicograficamente Ordenavel) resolve o mesmo problema que UUID v7 (IDs ordenaveis e ordenados por tempo) com um formato diferente. ULIDs usam timestamps de 48 bits em milissegundos e 80 bits de aleatoriedade, codificados como 26 caracteres Crockford Base32 (ex. 01ARZ3NDEKTSV4RRFFQ69G5FAV).
A diferença prática é a compatibilidade de formato. Se seu sistema espera strings em formato UUID (36 caracteres, hex, com hífens), use UUID v7. Se você quer identificadores mais curtos é seguros para URL e controla o formato de ponta a ponta, ULID é uma escolha razoável. Ambos são ordenados por tempo de geração; ambos evitam o problema B-tree.
UUID v7 tem a vantagem de ser um padrão IETF (RFC 9562), o que significa que o suporte do ecossistema esta crescendo rapidamente.
Dada uma string UUID, a versão esta sempre na posição 14 (indexada em 0), o primeiro caractere do terceiro grupo:
xxxxxxxx-xxxx-Vxxx-xxxx-xxxxxxxxxxxx
^
posição 14, sempre o digito da versão
1 → v1 (baseado em tempo, endereco MAC)3 → v3 (baseado em nome, MD5)4 → v4 (aleatório)5 → v5 (baseado em nome, SHA-1)7 → v7 (ordenado por tempo, aleatório)A variante esta na posição 19 (o primeiro caractere do quarto grupo): 8, 9, a ou b para UUIDs RFC 4122. Se você vir um 0 ou f na posição 14, o valor provavelmente não é um UUID padrão. Pode ser um UUID nulo, um UUID máximo ou um identificador não padrão com formato de UUID.
Nothing you paste leaves this tab. Every tool runs entirely in your browser — no upload, no server, no account.