UUID v7 Generator
Generate time-ordered UUID v7 for database primary keys
…
Formatieren
Was ist UUID v7?
UUID v7 ist ein Nächste-Generation-UUID-Format, das in RFC 9562 (Mai 2024) standardisiert ist. Es kodiert einen 48-Bit-Unix-Millisekunden-Zeitstempel in den signifikantesten Bits, gefolgt von Versions- und Variantenmarkern, und füllt die restlichen Bits mit kryptografisch sicheren Zufallsdaten.
Da der Zeitstempel die hohen Bits belegt, sortieren UUID v7-Werte chronologisch — sowohl lexikografisch als auch numerisch. Das macht sie zu einer hervorragenden Wahl für Datenbankprimärschlüssel, wo zufällige UUIDs (v4) B-Tree-Index-Fragmentierung verursachen.
Warum zufällige UUIDs Datenbankindizes fragmentieren
B-Tree-Indizes — verwendet von PostgreSQL, MySQL, SQLite und den meisten anderen Datenbanken — halten Zeilen nach Schlüsselwert sortiert. Wenn Sie eine neue Zeile einfügen, muss die Datenbank sie an der richtigen sortierten Position im Index platzieren.
Mit UUID v4 (vollständig zufällig) landet jedes neue Einfügen an einer im Wesentlichen zufälligen Position im Index-Baum. Dies zwingt die Datenbank dazu, interne Index-Seiten ständig zu lesen und neu zu schreiben, volle Seiten aufzuteilen und andere halb leer zu lassen. Das Ergebnis ist ein fragmentierter, aufgeblähter Index, der mit wachsender Tabelle sowohl Schreib- als auch Lesevorgänge verlangsamt.
UUID v7 Bit-Layout
UUID v7 ist 128 Bits breit, aufgeteilt in sechs Felder:
| Bits | Feld | Zweck |
|---|---|---|
| 48 | unix_ts_ms | 48-Bit-Unix-Zeitstempel in Millisekunden — belegt die gesamte obere Hälfte |
| 4 | ver | Versionsnummer — immer 0111 (dezimal 7) |
| 12 | rand_a | 12 Bits kryptografisch sicherer Zufallsdaten |
| 2 | var | Variantenmarker — immer 10 (RFC 4122-Variante) |
| 62 | rand_b | 62 Bits kryptografisch sicherer Zufallsdaten |
Die Zeitstempel-Präzision beträgt 1 Millisekunde. Innerhalb derselben Millisekunde werden UUID v7-Werte nach ihrem zufälligen Suffix geordnet — sie sind nicht garantiert sub-millisekunden-monoton steigend, aber sie sind k-sortierbar: IDs, die zeitlich nah beieinander generiert werden, sortieren im Index nah beieinander.
UUID v7 vs UUID v1
Sowohl UUID v1 als auch UUID v7 enthalten einen Zeitstempel, unterscheiden sich aber erheblich im Design:
| Merkmal | UUID v7 | UUID v1 |
|---|---|---|
| Epoche / Zeitbasis | Unix-Epoche (1. Jan. 1970) | Gregorianische Epoche (15. Okt. 1582) |
| Zeitpräzision | 1 Millisekunde | 100 Nanosekunden |
| Sortierbar | Ja — k-sortierbar by design | Nein — Zeitfelder sind im UUID-Layout verstreut |
| Datenschutz | Keine Host-Informationen preisgegeben | Enthält MAC-Adresse des generierenden Hosts |
| DB-Index-Performance | Hervorragend — sequentielle Einfügungen, minimale Fragmentierung | Schlecht — nicht-sequentiell trotz Zeitstempel |
| Standard | RFC 9562 (2024) | RFC 4122 (2005) |
| Native Browser-Unterstützung | Noch nicht (kein crypto.randomUUID v7) | Nativ nicht verfügbar |
Für jedes neue Projekt, das zeitgeordnete UUIDs benötigt, bevorzugen Sie UUID v7 gegenüber UUID v1. UUID v1 ist ein Legacy-Format und gibt Host-Informationen preis.
UUID v7 vs ULID
ULID (Universally Unique Lexicographically Sortable Identifier) löst ein ähnliches Problem wie UUID v7. Hier ist ein Vergleich:
- Folgt dem RFC 9562 UUID-Standard — kompatibel mit allen UUID-Tools
- Bindestriche-Hex-Format — universell erkannt
- Native Datenbank-UUID-Spalten-Unterstützung
- 128 Bits insgesamt
- Crockford Base32-Kodierung — 26 Zeichen, etwas kompakter
- Groß-/Kleinschreibung-unabhängig und vermeidet mehrdeutige Zeichen (I, L, O, U)
- Auf den ersten Blick besser menschenlesbar
- Erfordert eine Bibliothek — keine native Plattform-Unterstützung
Wenn Sie bereits in einem UUID-Ökosystem sind (PostgreSQL uuid-Spalte, REST-APIs, die UUIDs zurückgeben), verwenden Sie UUID v7. Wenn Sie neu beginnen und eine menschenfreundlichere Kodierung bevorzugen, ist ULID eine sinnvolle Alternative.
UUID v7 in Datenbanken verwenden
UUID v7 wird noch nicht nativ von den meisten Datenbanken generiert, kann aber in Standard-UUID-Spalten gespeichert und im Anwendungscode oder über Erweiterungen generiert werden:
uuid-Spalte speichern. Die Erweiterung pg-uuidv7 fügt eine serverseitige Funktion uuid_generate_v7() hinzu, wenn Sie datenbankgenerierte IDs benötigen.BINARY(16)- oder CHAR(36)-Spalte speichern. Im Anwendungscode generieren. MySQL 8.0+ hat geordnete UUID-Unterstützung über UUID_TO_BIN(UUID(), 1) für v1, aber v7 erfordert App-Level-Generierung.TEXT (36 Zeichen) oder BLOB (16 Bytes) speichern. Im Anwendungscode generieren. Lexikografische Sortierung auf TEXT funktioniert korrekt, da UUID v7 ein Zeitstempel-Präfix fester Breite verwendet.Code-Beispiele
UUID v7 ist noch nicht über crypto.randomUUID() verfügbar. Verwenden Sie eine Bibliothek wie uuidv7 (npm), bis native Unterstützung kommt:
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"