Générateur UUID v7
Génère des UUID v7 ordonnés dans le temps pour les clés primaires de bases de données
…
Formater
Qu'est-ce qu'UUID v7 ?
UUID v7 est un format UUID de nouvelle génération standardisé dans RFC 9562 (mai 2024). Il encode un horodatage Unix de 48 bits en millisecondes dans les bits de poids fort, suivi de marqueurs de version et de variante, et remplit les bits restants avec des données aléatoires cryptographiquement sécurisées.
Comme l'horodatage occupe les bits de poids fort, les valeurs UUID v7 se trient chronologiquement — à la fois lexicographiquement et numériquement. Cela en fait un excellent choix pour les clés primaires de base de données, où les UUID aléatoires (v4) causent une fragmentation des index B-tree.
Pourquoi les UUID aléatoires fragmentent les index de base de données
Les index B-tree — utilisés par PostgreSQL, MySQL, SQLite et la plupart des autres bases de données — maintiennent les lignes triées par valeur de clé. Lors de l'insertion d'une nouvelle ligne, la base de données doit la placer à la position triée correcte dans l'arbre d'index.
Avec UUID v4 (entièrement aléatoire), chaque nouvel insert atterrit à une position essentiellement aléatoire dans l'arbre d'index. Cela force la base de données à lire et réécrire constamment les pages d'index internes, fragmentant les pages pleines et en laissant d'autres à moitié vides. Le résultat est un index fragmenté et gonflé qui ralentit à la fois les écritures et les lectures à mesure que la table croît.
Disposition des bits d'UUID v7
UUID v7 fait 128 bits de large, divisé en six champs :
| Bits | Champ | Objectif |
|---|---|---|
| 48 | unix_ts_ms | Horodatage Unix de 48 bits en millisecondes — occupe toute la moitié haute |
| 4 | ver | Numéro de version — toujours 0111 (décimal 7) |
| 12 | rand_a | 12 bits de données aléatoires cryptographiquement sécurisées |
| 2 | var | Marqueur de variante — toujours 10 (variante RFC 4122) |
| 62 | rand_b | 62 bits de données aléatoires cryptographiquement sécurisées |
La précision de l'horodatage est de 1 milliseconde. Dans la même milliseconde, les valeurs UUID v7 sont ordonnées par leur suffixe aléatoire — elles ne sont pas garanties d'être monotoniquement croissantes en dessous de la milliseconde, mais elles sont k-sortables : les identifiants générés proches dans le temps se trieront proches dans l'index.
UUID v7 vs UUID v1
UUID v1 et UUID v7 intègrent tous deux un horodatage, mais ils diffèrent significativement dans leur conception :
| Fonctionnalité | UUID v7 | UUID v1 |
|---|---|---|
| Epoch / Base temporelle | Epoch Unix (1er jan. 1970) | Epoch grégorien (15 oct. 1582) |
| Précision temporelle | 1 milliseconde | 100 nanosecondes |
| Triable | Oui — k-sortable par conception | Non — les champs temporels sont brouillés dans la disposition UUID |
| Confidentialité | Aucune information sur l'hôte divulguée | Intègre l'adresse MAC de l'hôte générateur |
| Performance d'index BD | Excellente — inserts séquentiels, fragmentation minimale | Médiocre — non séquentiel malgré l'horodatage |
| Standard | RFC 9562 (2024) | RFC 4122 (2005) |
| Support natif navigateur | Pas encore (pas de crypto.randomUUID v7) | Non disponible nativement |
Pour tout nouveau projet nécessitant des UUID ordonnés dans le temps, préférez UUID v7 à UUID v1. UUID v1 est legacy et divulgue des informations sur l'hôte.
UUID v7 vs ULID
ULID (Universally Unique Lexicographically Sortable Identifier) résout un problème similaire à UUID v7. Voici comment ils se comparent :
- Suit la norme UUID RFC 9562 — compatible avec tous les outils UUID
- Format hexadécimal avec tirets — universellement reconnu
- Support natif de colonne UUID dans les bases de données
- 128 bits au total
- Encodage Crockford Base32 — 26 caractères, légèrement plus compact
- Insensible à la casse et évite les caractères ambigus (I, L, O, U)
- Plus lisible par l'humain au premier coup d'oeil
- Nécessite une bibliothèque — aucun support natif de plateforme
Si vous êtes déjà dans un écosystème UUID (colonne uuid PostgreSQL, API REST retournant des UUID), utilisez UUID v7. Si vous partez de zéro et préférez un encodage plus convivial, ULID est une alternative raisonnable.
Utiliser UUID v7 dans les bases de données
UUID v7 n'est pas encore généré nativement par la plupart des bases de données, mais peut être stocké dans des colonnes UUID standard et généré dans le code applicatif ou via des extensions :
uuid. L'extension pg-uuidv7 ajoute une fonction côté serveur uuid_generate_v7() si vous avez besoin d'identifiants générés par la BD.BINARY(16) ou CHAR(36). Générez dans le code applicatif. MySQL 8.0+ dispose du support UUID ordonné via UUID_TO_BIN(UUID(), 1) pour v1, mais v7 nécessite une génération au niveau applicatif.TEXT (36 chars) ou BLOB (16 octets). Générez dans le code applicatif. Le tri lexicographique sur TEXT fonctionne correctement car UUID v7 utilise un préfixe d'horodatage à largeur fixe.Exemples de code
UUID v7 n'est pas encore disponible via crypto.randomUUID(). Utilisez une bibliothèque telle que uuidv7 (npm) jusqu'à l'arrivée du support natif :
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"