UUID v7 Generator

Generate time-ordered UUID v7 for database primary keys

Formatera

Antal:

Vad är UUID v7?

UUID v7 är ett nästa generations UUID-format standardiserat i RFC 9562 (maj 2024). Det kodar en 48-bitars Unix-millisekundtidsstämpel i de mest signifikanta bitarna, följt av versions- och variantmarkörer, och fyller de återstående bitarna med kryptografiskt säkra slumpmässiga data.

Eftersom tidsstämpeln upptar de höga bitarna sorteras UUID v7-värden kronologiskt — både lexikografiskt och numeriskt. Det gör dem till ett utmärkt val för databasprimärnycklar, där slumpmässiga UUID:n (v4) orsakar B-tree-indexfragmentering.

Varför slumpmässiga UUID:n fragmenterar databasindex

B-tree-index — som används av PostgreSQL, MySQL, SQLite och de flesta andra databaser — håller rader sorterade efter nyckelvärde. När du infogar en ny rad måste databasen placera den på rätt sorterad position i indexet.

Med UUID v4 (helt slumpmässigt) landar varje ny infogning på en i princip slumpmässig position i indexträdet. Det tvingar databasen att konstant läsa och skriva om interna indexsidor, dela upp fulla sidor och lämna andra halvtomma. Resultatet är ett fragmenterat, uppblåst index som bromsar både skrivningar och läsningar när tabellen växer.

UUID v7 bitlayout

UUID v7 är 128 bitar brett, uppdelat i sex fält:

BitarFältSyfte
48unix_ts_ms48-bitars Unix-tidsstämpel i millisekunder — upptar hela den höga hälften
4verVersionsnummer — alltid 0111 (decimalt 7)
12rand_a12 bitar kryptografiskt säkra slumpmässiga data
2varVariantmarkör — alltid 10 (RFC 4122-variant)
62rand_b62 bitar kryptografiskt säkra slumpmässiga data

Tidsstämpelprecisionen är 1 millisekund. Inom samma millisekund ordnas UUID v7-värden av deras slumpmässiga suffix — de garanteras inte vara monotont ökande sub-millisekund, men de är k-sorterbara: ID:n som genereras nära varandra i tid sorteras nära varandra i indexet.

UUID v7 vs UUID v1

Både UUID v1 och UUID v7 innehåller en tidsstämpel, men de skiljer sig avsevärt i design:

FunktionUUID v7UUID v1
Epok / TidsbasUnix-epok (1 jan 1970)Gregoriansk epok (15 okt 1582)
Tidsprecision1 millisekund100 nanosekunder
SorterbarJa — k-sorterbar by designNej — tidsfält är blandade i UUID-layouten
IntegritetIngen värdinformation läcktInbäddar MAC-adress från genererande värd
DB-indexprestandaUtmärkt — sekventiella infogningar, minimal fragmenteringDålig — icke-sekventiell trots tidsstämpel
StandardRFC 9562 (2024)RFC 4122 (2005)
Inbyggt webbläsarstödÄnnu inte (inget crypto.randomUUID v7)Inte tillgängligt inbyggt

För alla nya projekt som behöver tidsordnade UUID:n, föredra UUID v7 framför UUID v1. UUID v1 är ett äldre format och läcker värdinformation.

UUID v7 vs ULID

ULID (Universally Unique Lexicographically Sortable Identifier) löser ett liknande problem som UUID v7. Här är en jämförelse:

UUID v7
  • Följer RFC 9562 UUID-standarden — kompatibel med all UUID-tooling
  • Bindestreck-hexformat — universellt erkänt
  • Inbyggt databasstöd för UUID-kolumner
  • 128 bitar totalt
ULID
  • Crockford Base32-kodning — 26 tecken, något mer kompakt
  • Skiftlägeskänsligt och undviker tvetydiga tecken (I, L, O, U)
  • Mer mänskligt läsbar vid en snabb blick
  • Kräver ett bibliotek — inget inbyggt plattformsstöd

Om du redan befinner dig i ett UUID-ekosystem (PostgreSQL uuid-kolumn, REST-API:er som returnerar UUID:n), använd UUID v7. Om du börjar från scratch och föredrar en mer användarvänlig kodning, är ULID ett rimligt alternativ.

Använda UUID v7 i databaser

UUID v7 genereras ännu inte inbyggt av de flesta databaser, men kan lagras i standard UUID-kolumner och genereras i applikationskod eller via tillägg:

PostgreSQL
PostgreSQL: lagra i en uuid-kolumn. Tillägget pg-uuidv7 lägger till en uuid_generate_v7() serversidsfunktion om du behöver DB-genererade ID:n.
MySQL / MariaDB
MySQL / MariaDB: lagra i en BINARY(16) eller CHAR(36)-kolumn. Generera i applikationskod. MySQL 8.0+ har ordnat UUID-stöd via UUID_TO_BIN(UUID(), 1) för v1, men v7 kräver generering på applikationsnivå.
SQLite
SQLite: lagra som TEXT (36 tecken) eller BLOB (16 byte). Generera i applikationskod. Lexikografisk sortering på TEXT fungerar korrekt eftersom UUID v7 använder ett tidsstämpelprefix med fast bredd.

Kodexempel

UUID v7 är ännu inte tillgängligt via crypto.randomUUID(). Använd ett bibliotek som uuidv7 (npm) tills inbyggt stöd anländer:

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"

Vanliga frågor

Är UUID v7 bakåtkompatibelt med UUID v4?
Ja. UUID v7 använder samma 128-bitars, 32-hex-siffror, bindestreck-trådformat som alla andra UUID-versioner. Alla system som lagrar eller överför UUID:n accepterar ett UUID v7 utan ändringar. Versionsnibble (7) och variantbitar identifierar det som v7 för verktyg som inspekterar UUID-struktur.
Avslöjar UUID v7 genereringstidsstämpeln?
Ja — de första 48 bitarna är en Unix-millisekundtidsstämpel, så vem som helst med UUID kan avgöra ungefär när det genererades (till närmaste millisekund). Om att exponera skapandetid är ett problem för ditt användningsfall, använd UUID v4 istället.
Kan jag använda UUID v7 som en databaspriärnyckel utan en separat created_at-kolumn?
Ja. Eftersom UUID v7 bäddar in en millisekundprecisionstidsstämpel kan du avkoda det värdet för att få den ungefärliga skapandetiden. Men för tydlighet och indexerbarhet behåller många team fortfarande en explicit created_at-kolumn och använder UUID v7 bara för ID-kolumnen.
Hur mycket entropi har UUID v7?
UUID v7 har 74 bitar slumpmässiga data (12 bitar i rand_a + 62 bitar i rand_b). Det är något mindre än UUID v4:s 122 bitar men ger fortfarande ett astronomiskt stort kollisionsfritt utrymme för praktisk användning. Den minskade slumpmässigheten är avvägningen för att vinna tidsstämpelsorterbarhet.
Stöds UUID v7 inbyggt i webbläsare eller Node.js?
Ännu inte i början av 2025. RFC 9562-standarden publicerades i maj 2024 och plattformsstöd är fortfarande på väg. Använd npm-paketet uuidv7 för nu. Inbyggt stöd via crypto.randomUUID{ version: 7 } eller liknande API:er kan komma i framtida webbläsare och Node.js-versioner.