UUID v7 Generator

Generate time-ordered UUID v7 for database primary keys

Форматувати

Кількість:

Що таке UUID v7?

UUID v7 — UUID-формат нового покоління, стандартизований у RFC 9562 (травень 2024). Він кодує 48-бітну Unix-часову мітку в мілісекундах у найзначущих бітах, а решта бітів заповнюється криптографічно захищеними випадковими даними.

Оскільки часова мітка займає старші біти, значення UUID v7 сортуються хронологічно — як лексикографічно, так і чисельно. Це робить їх чудовим вибором для первинних ключів БД, де випадкові UUID (v4) спричиняють фрагментацію B-tree-індексу.

Чому випадкові UUID фрагментують індекси баз даних

B-tree-індекси — у PostgreSQL, MySQL, SQLite та більшості БД — зберігають рядки відсортованими за значенням ключа. При вставці нового рядка БД має розмістити його в правильній відсортованій позиції.

При UUID v4 (повністю випадковому) кожна нова вставка потрапляє у випадкову позицію в дереві індексу, змушуючи БД постійно читати й перезаписувати сторінки індексу — створюючи фрагментований, роздутий індекс.

Бітова структура UUID v7

UUID v7 має 128 бітів і ділиться на шість полів:

БітиПолеПризначення
48unix_ts_ms48-бітна Unix-часова мітка в мілісекундах — займає всю старшу половину
4verНомер версії — завжди 0111 (десяткове 7)
12rand_a12 бітів криптографічно захищених випадкових даних
2varМаркер варіанта — завжди 10 (варіант RFC 4122)
62rand_b62 біти криптографічно захищених випадкових даних

Комбінація часової мітки + випадкових даних дає 74 біти ентропії в межах кожної мілісекунди — достатньо для тисяч унікальних UUID без колізій.

UUID v7 проти UUID v1

Обидва кодують часову мітку, але підходи принципово різні:

ХарактеристикаUUID v7UUID v1
ЕпохаUnix (1 січня 1970)Gregorian (15 жовтня 1582)
Точність часуМілісекунди100 наносекунд
Лексикографічно сортованийТакНі
КонфіденційністьНе розкриває MACРозкриває MAC-адресу хоста
Продуктивність індексу БДВідмінна (монотонна вставка)Погана (випадкові позиції)
СтандартRFC 9562 (2024)RFC 4122 (2005)
Підтримка в браузеріНемає нативного APIНемає нативного API

Для нових проектів переважно UUID v7. Єдина причина використовувати v1 — сумісність з існуючими системами.

UUID v7 проти ULID

UUID v7 і ULID вирішують одну і ту саму проблему — сортовані унікальні ID — але з різними компромісами:

UUID v7
  • <strong>UUID v7</strong>: Стандарт IETF (RFC 9562), 128-бітний, нативна підтримка в будь-якій системі, що розуміє UUID.
  • <strong>UUID v7</strong>: Монотонний у межах однієї мілісекунди при правильній реалізації, 122 біти ентропії.
  • <strong>UUID v7</strong>: Менш компактний — 36 символів із дефісами або 32 без них.
  • <strong>UUID v7</strong>: Немає нативного API в браузері; потребує бібліотеку.
ULID
  • <strong>ULID</strong>: Специфікація спільноти, широко використовується. 26 символів у кодуванні Crockford Base32.
  • <strong>ULID</strong>: Компактніший і читабельніший. URL-безпечний, нечутливий до регістру.
  • <strong>ULID</strong>: 128 бітів, але інша байтова схема — несумісний із форматом UUID.
  • <strong>ULID</strong>: Монотонний режим доступний у більшості реалізацій.

Використовуйте UUID v7 для сумісності з UUID. ULID — якщо компактність важливіша за сумісність.

Підтримка баз даних

Підтримка нативного UUID v7 додається в бази даних:

PostgreSQL
PostgreSQL 17+ включає підтримку UUID v7. Для старіших версій використовуйте розширення pg_uuidv7.
MySQL / MariaDB
MySQL/MariaDB: використовуйте стовпець BINARY(16) або VARCHAR(36). Нема нативного типу UUID v7.
SQLite
SQLite: зберігається як TEXT або BLOB. Підтримка на рівні застосунку.

Приклади коду

UUID v7 ще не підтримується нативно в браузерах або Node.js. Використовуйте бібліотеку:

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"

Часті запитання

Чи є UUID v7 зворотно сумісним з UUID v4?
Так щодо формату: UUID v7 — все ще 128-бітне значення у стандартному UUID-представленні. Будь-яка система, що зберігає UUID як <code>VARCHAR(36)</code> або <code>UUID</code>, прийме UUID v7 без змін.
Чи розкриває UUID v7 час генерації?
UUID v7 містить 48-бітну Unix-часову мітку в мілісекундах — достатньо для відновлення часу генерації. Якщо конфіденційність вимагає приховування часу створення, використовуйте UUID v4.
Чи можна генерувати UUID v7 у браузері?
Не нативно. Використовуйте npm-пакети (наприклад, <code>uuidv7</code>) або реалізуйте самостійно з <code>Date.now()</code> та <code>crypto.getRandomValues()</code>.
Чи гарантований порядок UUID v7 при генерації кількох UUID за одну мілісекунду?
Лише якщо реалізація підтримує монотонний режим. У монотонному режимі генератор інкрементує випадкову частину при кожному виклику протягом тієї ж мілісекунди.
Чому RFC 9562 застаріває деякі частини RFC 4122?
RFC 9562 (2024) додає UUID v6, v7 і v8. Він застаріває UUID v1 на користь v6 і v3 на користь v5. UUID v4 залишається рекомендованим для випадкових ID.