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

Quantité:

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 :

BitsChampObjectif
48unix_ts_msHorodatage Unix de 48 bits en millisecondes — occupe toute la moitié haute
4verNuméro de version — toujours 0111 (décimal 7)
12rand_a12 bits de données aléatoires cryptographiquement sécurisées
2varMarqueur de variante — toujours 10 (variante RFC 4122)
62rand_b62 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 v7UUID v1
Epoch / Base temporelleEpoch Unix (1er jan. 1970)Epoch grégorien (15 oct. 1582)
Précision temporelle1 milliseconde100 nanosecondes
TriableOui — k-sortable par conceptionNon — les champs temporels sont brouillés dans la disposition UUID
ConfidentialitéAucune information sur l'hôte divulguéeIntègre l'adresse MAC de l'hôte générateur
Performance d'index BDExcellente — inserts séquentiels, fragmentation minimaleMédiocre — non séquentiel malgré l'horodatage
StandardRFC 9562 (2024)RFC 4122 (2005)
Support natif navigateurPas 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 :

UUID v7
  • 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
ULID
  • 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 :

PostgreSQL
PostgreSQL : stockez dans une colonne 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.
MySQL / MariaDB
MySQL / MariaDB : stockez dans une colonne 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.
SQLite
SQLite : stockez en 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 :

JavaScript (browser / Node.js 20+)
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
Python (uuid7 library)
# 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 — generate UUID v7
-- 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()
);
TypeScript — extract timestamp from UUID v7
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"

Foire Aux Questions

UUID v7 est-il rétrocompatible avec UUID v4 ?
Oui. UUID v7 utilise le même format wire de 128 bits, 32 chiffres hexadécimaux, avec tirets que toutes les autres versions UUID. Tout système qui stocke ou transmet des UUID acceptera un UUID v7 sans changement. Le nibble de version (7) et les bits de variante l'identifient comme v7 pour les outils inspectant la structure UUID.
UUID v7 expose-t-il l'horodatage de génération ?
Oui — les 48 premiers bits sont un horodatage Unix en millisecondes, donc quiconque possède l'UUID peut déterminer approximativement quand il a été généré (à la milliseconde près). Si exposer le temps de création est une préoccupation pour votre cas d'usage, utilisez plutôt UUID v4.
Puis-je utiliser UUID v7 comme clé primaire de base de données sans colonne created_at séparée ?
Oui. Comme UUID v7 intègre un horodatage de précision milliseconde, vous pouvez décoder cette valeur pour obtenir le temps de création approximatif. Cependant, pour la clarté et l'indexabilité, de nombreuses équipes conservent quand même une colonne created_at explicite et utilisent UUID v7 uniquement pour la colonne d'ID.
Quelle est l'entropie d'UUID v7 ?
UUID v7 dispose de 74 bits de données aléatoires (12 bits dans rand_a + 62 bits dans rand_b). C'est légèrement moins que les 122 bits d'UUID v4 mais fournit toujours un espace sans collision astronomiquement grand pour un usage pratique. La réduction d'aléatoire est le compromis pour obtenir la triabilité par horodatage.
UUID v7 est-il supporté nativement dans les navigateurs ou Node.js ?
Pas encore début 2025. La norme RFC 9562 a été publiée en mai 2024 et le support des plateformes rattrape encore. Utilisez le package npm uuidv7 pour l'instant. Le support natif via crypto.randomUUID({ version: 7 }) ou des API similaires pourrait arriver dans de futures versions de navigateurs et Node.js.