Gerador UUID v7
Gera UUID v7 ordenados por tempo para chaves primárias de banco de dados
…
Formatar
O que é UUID v7?
UUID v7 é um formato de UUID de próxima geração padronizado no RFC 9562 (maio de 2024). Ele codifica um timestamp Unix de 48 bits em milissegundos nos bits mais significativos, seguido de marcadores de versão e variante, e preenche os bits restantes com dados aleatórios criptograficamente seguros.
Como o timestamp ocupa os bits mais significativos, os valores UUID v7 são ordenados cronologicamente — tanto lexicograficamente quanto numericamente. Isso os torna excelentes para chaves primárias de banco de dados, onde UUIDs aleatórios (v4) causam fragmentação no índice B-tree.
Por que UUIDs Aleatórios Fragmentam Índices de Banco de Dados
Índices B-tree — usados pelo PostgreSQL, MySQL, SQLite e a maioria dos outros bancos de dados — mantêm as linhas ordenadas por valor de chave. Quando você insere uma nova linha, o banco de dados deve colocá-la na posição ordenada correta dentro do índice.
Com UUID v4 (totalmente aleatório), cada nova inserção cai em uma posição essencialmente aleatória na árvore de índice. Isso força o banco de dados a ler e reescrever páginas de índice internas constantemente, dividindo páginas cheias e deixando outras pela metade. O resultado é um índice fragmentado e inchado que desacelera tanto escritas quanto leituras conforme a tabela cresce.
Layout de Bits do UUID v7
UUID v7 tem 128 bits de largura, dividido em seis campos:
| Bits | Campo | Propósito |
|---|---|---|
| 48 | unix_ts_ms | Timestamp Unix de 48 bits em milissegundos — ocupa toda a metade superior |
| 4 | ver | Número de versão — sempre 0111 (decimal 7) |
| 12 | rand_a | 12 bits de dados aleatórios criptograficamente seguros |
| 2 | var | Marcador de variante — sempre 10 (variante RFC 4122) |
| 62 | rand_b | 62 bits de dados aleatórios criptograficamente seguros |
A precisão do timestamp é de 1 milissegundo. Dentro do mesmo milissegundo, os valores UUID v7 são ordenados pelo sufixo aleatório — não há garantia de que sejam monotonicamente crescentes abaixo do milissegundo, mas são k-ordenáveis: IDs gerados próximos no tempo serão ordenados próximos no índice.
UUID v7 vs UUID v1
Tanto UUID v1 quanto UUID v7 incorporam um timestamp, mas diferem significativamente no design:
| Característica | UUID v7 | UUID v1 |
|---|---|---|
| Época / Base de Tempo | Época Unix (1 jan. 1970) | Época gregoriana (15 out. 1582) |
| Precisão de Tempo | 1 milissegundo | 100 nanossegundos |
| Ordenável | Sim — k-ordenável por design | Não — campos de tempo embaralhados no layout UUID |
| Privacidade | Nenhuma informação do host vazada | Incorpora endereço MAC do host gerador |
| Desempenho de Índice BD | Excelente — inserções sequenciais, fragmentação mínima | Ruim — não sequencial apesar do timestamp |
| Padrão | RFC 9562 (2024) | RFC 4122 (2005) |
| Suporte Nativo no Navegador | Ainda não (sem crypto.randomUUID v7) | Não disponível nativamente |
Para qualquer novo projeto que precise de UUIDs ordenados por tempo, prefira UUID v7 a UUID v1. UUID v1 é legado e vaza informações do host.
UUID v7 vs ULID
ULID (Identificador Universalmente Único Lexicograficamente Ordenável) resolve um problema semelhante ao UUID v7. Veja como eles se comparam:
- Segue o padrão UUID RFC 9562 — compatível com todas as ferramentas UUID
- Formato hexadecimal com hífens — universalmente reconhecido
- Suporte nativo a coluna UUID no banco de dados
- 128 bits no total
- Codificação Crockford Base32 — 26 caracteres, ligeiramente mais compacto
- Insensível a maiúsculas e evita caracteres ambíguos (I, L, O, U)
- Mais legível para humanos à primeira vista
- Requer uma biblioteca — sem suporte nativo de plataforma
Se você já está em um ecossistema UUID (coluna uuid do PostgreSQL, APIs REST retornando UUIDs), use UUID v7. Se está começando do zero e prefere uma codificação mais amigável para humanos, ULID é uma alternativa razoável.
Usando UUID v7 em Bancos de Dados
UUID v7 ainda não é gerado nativamente pela maioria dos bancos de dados, mas pode ser armazenado em colunas UUID padrão e gerado no código da aplicação ou via extensões:
uuid. A extensão pg-uuidv7 adiciona uma função uuid_generate_v7() do lado do servidor se você precisar de IDs gerados pelo BD.BINARY(16) ou CHAR(36). Gere no código da aplicação. MySQL 8.0+ tem suporte a UUID ordenado via UUID_TO_BIN(UUID(), 1) para v1, mas v7 requer geração em nível de aplicação.TEXT (36 chars) ou BLOB (16 bytes). Gere no código da aplicação. A ordenação lexicográfica em TEXT funciona corretamente porque UUID v7 usa um prefixo de timestamp de largura fixa.Exemplos de Código
UUID v7 ainda não está disponível via crypto.randomUUID(). Use uma biblioteca como uuidv7 (npm) até que o suporte nativo chegue:
function generateUuidV7() {
const buf = new Uint8Array(16)
crypto.getRandomValues(buf)
const ms = BigInt(Date.now())
// Embed 48-bit Unix ms timestamp
buf[0] = Number((ms >> 40n) & 0xFFn)
buf[1] = Number((ms >> 32n) & 0xFFn)
buf[2] = Number((ms >> 24n) & 0xFFn)
buf[3] = Number((ms >> 16n) & 0xFFn)
buf[4] = Number((ms >> 8n) & 0xFFn)
buf[5] = Number(ms & 0xFFn)
// Set version 7 (0111xxxx)
buf[6] = (buf[6] & 0x0F) | 0x70
// Set variant (10xxxxxx)
buf[8] = (buf[8] & 0x3F) | 0x80
const hex = [...buf].map(b => b.toString(16).padStart(2, '0')).join('')
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`
}
// Node.js 20+ built-in
// import { randomUUID } from 'node:crypto' // v4 only — no v7 yet in stdlib# pip install uuid7 import uuid_extensions uid = uuid_extensions.uuid7() print(uid) # e.g. 018e2b3d-1a2b-7000-8000-abc123456789 print(uid.time) # Unix ms timestamp embedded in the UUID # Or as a plain string from uuid_extensions import uuid7str print(uuid7str())
-- PostgreSQL 13+ extension-free implementation
CREATE OR REPLACE FUNCTION uuid_generate_v7()
RETURNS uuid
LANGUAGE sql
AS $$
SELECT encode(
set_bit(
set_bit(
overlay(
uuid_send(gen_random_uuid())
PLACING substring(int8send(floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint) FROM 3)
FROM 1 FOR 6
),
52, 1
),
53, 1
),
'hex'
)::uuid;
$$;
-- Usage as a default primary key
CREATE TABLE events (
id uuid PRIMARY KEY DEFAULT uuid_generate_v7(),
payload jsonb,
created_at timestamptz DEFAULT now()
);function extractTimestamp(uuid: string): Date {
const hex = uuid.replace(/-/g, '')
const ms = parseInt(hex.slice(0, 12), 16) // first 48 bits = ms timestamp
return new Date(ms)
}
const uid = '018e2b3d-1a2b-7000-8000-abc123456789'
console.log(extractTimestamp(uid).toISOString())
// → "2024-03-15T10:22:05.259Z"