Gerador de UUID

Gere UUIDs v4 ou v7 ordenados por tempo, e inspecione os que você já tem.

5

UUID aleatórios

    Inspecionar um UUID

    Cole um para ver de que versão é e o que, se é que alguma coisa, tem embutido.

    As versões, e quais duas interessam

    São oito, e para trabalho novo a escolha é realmente entre duas. Vale a pena reconhecer as restantes quando as encontrar num sistema antigo.

    VersãoConstruída a partir deUse quando
    v4122 bits aleatóriosPrecisa de algo impossível de adivinhar. A opção por omissão para tokens e identificadores.
    v7Marca temporal + aleatoriedadePrecisa de uma chave de base de dados. Ordena por hora de criação.
    v1Marca temporal + endereço MACLegado. Revela a máquina e a hora.
    v3 / v5Resumo de um espaço de nomes e de um nomePrecisa que a mesma entrada dê sempre o mesmo identificador.
    v6v1, reordenadaEstá a migrar dados v1 e quer que fiquem ordenados.
    v8Aquilo que decidirQuase nunca.

    O problema do índice, que é a verdadeira razão de existir da v7

    É este o argumento prático, e vale mais compreendê-lo do que aceitá-lo de fé.

    Uma chave primária é guardada numa árvore B, ordenada. Insira inteiros sequenciais e cada nova linha cai na extremidade direita: uma página fica quente em memória, a árvore cresce arrumada e as escritas são baratas.

    Insira UUID v4 e cada linha cai num sítio ao acaso. Tocam-se páginas por toda a árvore, cada uma tem de ser lida antes de poder ser escrita, e as páginas dividem-se à medida que enchem. Numa tabela de qualquer dimensão, o débito de inserção cai visivelmente e o índice fragmenta-se — o efeito está bem documentado e foi ele que deu às chaves UUID a fama que têm.

    A v7 resolve isso pondo a marca temporal à frente. Gere acima um punhado com a v7 seleccionada e repare no prefixo comum: valores criados em alturas próximas ficam adjacentes, portanto as inserções acrescentam-se ao fim do índice como um inteiro, mantendo-se globalmente únicas. Fica com a propriedade que tornou os UUID atraentes — gerar um identificador em qualquer lado, sem coordenação nenhuma — sem a pagar em cada escrita.

    Com rigor: a ordenação é garantida entre milissegundos, não dentro de um. Dois UUID v7 gerados no mesmo milissegundo ordenam-se pelas suas caudas aleatórias, o que o RFC 9562 permite, deixando às implementações a opção de apertar isso com um contador. Não faz diferença nenhuma para o argumento da localidade do índice, que depende apenas da marca temporal inicial.

    O custo que fica para ambas: 16 bytes contra 4 ou 8, replicados em todos os índices que referenciem a chave. Numa tabela grande com várias chaves estrangeiras, isso é disco a sério.

    O que a v7 revela

    A marca temporal é legível por quem tiver o identificador. Cole um UUID v7 no inspector acima e ele dir-lhe-á o milissegundo em que foi criado.

    Normalmente inofensivo. Ocasionalmente não: um identificador v7 num URL público revela quando um registo foi criado, o que pode chegar para inferir ritmos de inscrição, volumes de encomendas, ou que um documento foi datado para trás. Se isso importa, a divisão simples é v4 para tudo o que o utilizador vê e v7 para as chaves internas.

    Onde a aleatoriedade tem de ser real

    A aritmética das colisões que toda a gente cita — 2,7 triliões antes de a hipótese de uma colisão chegar a cara ou coroa — pressupõe 122 bits genuinamente aleatórios. É uma afirmação sobre o formato, não sobre a sua implementação.

    Um UUID construído sobre Math.random() não tem nem a entropia nem a imprevisibilidade que aquele número sugere, e as colisões no mundo real foram, no essencial, sempre isto e não azar. Dois processos iniciados no mesmo segundo com a mesma semente produzem a mesma sequência.

    Esta página usa crypto.randomUUID() onde existe e crypto.getRandomValues no resto. Vale a pena verificar o que o seu próprio código usa, sobretudo se os UUID estiverem a fazer as vezes de tokens — um identificador previsível de reposição de palavra-passe é uma tomada completa da conta.

    Guardá-los de forma eficiente

    A forma textual de 36 caracteres é cómoda e esbanjadora. As alternativas, todas os mesmos 128 bits:

    • Tipo UUID nativo — o Postgres tem um, e guarda 16 bytes. Use-o.
    • `BINARY(16)` — o equivalente no MySQL, cerca de metade do armazenamento de CHAR(36).
    • Base64 — 22 caracteres, quando tem mesmo de ser texto e o comprimento conta.
    • Base32 — 26 caracteres, sem distinção de maiúsculas, que é o que quer se alguma vez um humano tiver de ler um em voz alta.

    Relacionado

    Para segredos que uma pessoa tem de escrever em vez de uma máquina os guardar, o gerador de palavras-passe usa a mesma fonte de aleatoriedade. Para ler a marca temporal de um UUID v7 noutro formato, o conversor de marcas temporais segue daí.

    Perguntas sobre UUID

    Dois UUID podem colidir?

    Em princípio sim; na prática não, desde que a aleatoriedade seja real. Um UUID v4 tem 122 bits aleatórios, e seria preciso gerar cerca de 2,7 triliões deles para chegar a 50 % de hipóteses de uma única colisão — algo como mil milhões por segundo durante 85 anos. A falha realista nunca está na matemática: está numa fonte de aleatoriedade fraca. Um UUID construído sobre Math.random() ou sobre um gerador mal semeado pode colidir e colide, e é por isso que esta página usa a fonte criptográfica do navegador.

    Devo usar um UUID como chave primária de base de dados?

    Depende da versão, e a diferença é grande. Um UUID v4 é aleatório, portanto inserções consecutivas caem em pontos ao acaso de um índice em árvore B — as páginas dividem-se, o índice fragmenta-se e o débito de escrita cai de forma mensurável numa tabela grande. Um UUID v7 começa por uma marca temporal em milissegundos, portanto as inserções acrescentam-se no fim como num inteiro auto-incrementado, mantendo a unicidade global. Se quer chaves UUID, use v7. O outro custo aplica-se a ambos: 16 bytes contra 4 ou 8 de um inteiro, em todos os índices que lhe façam referência.

    O que é o UUID v7 e já é seguro usá-lo?

    É ordenado no tempo: 48 bits de milissegundos Unix seguidos de 74 bits aleatórios, normalizado no RFC 9562 em Maio de 2024. É uma norma publicada, com suporte no Postgres actual, na maioria dos ecossistemas de linguagens e num bom número de bibliotecas. É um valor por omissão razoável para trabalho novo. A propriedade a ter em conta é que incorpora um instante de criação, por isso um identificador v7 num URL revela aproximadamente quando o registo foi feito.

    Um UUID é suficientemente seguro para servir de token?

    Um UUID v4 vindo de uma fonte criptográfica tem 122 bits de entropia, o que chega e sobra para uma ligação de reposição de palavra-passe ou um identificador de sessão. Duas ressalvas. Primeira, a fonte tem mesmo de ser criptográfica — crypto.randomUUID é, a maioria das implementações de bibliotecas também, e tudo o que assente em Math.random() não é. Segunda, as outras versões não servem: a v1 incorpora uma marca temporal e, historicamente, um endereço MAC; a v3 e a v5 são resumos determinísticos das suas entradas; e a v7 revela o instante de criação. Se tem de ser impossível de adivinhar, use v4.

    Porque é que um UUID tem 36 caracteres se são apenas 16 bytes?

    Porque é escrito em hexadecimal — dois caracteres por byte, logo 32 — mais quatro hífenes. Alguns sistemas guardam antes os 16 bytes em bruto, que é para isso que serve o BINARY(16) do MySQL e que reduz o armazenamento a cerca de metade. Outros usam uma codificação de texto mais curta: o Base64 dá 22 caracteres, o Base32 dá 26 e não distingue maiúsculas de minúsculas. Todos eles são os mesmos 128 bits com outra roupa.

    Última revisão . Encontrou algo desactualizado? Diga-nos.