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 v7 и 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 символов в Base32-кодировке Crockford.
  • <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-представлении. Любая система, принимающая <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.