EN
Назад к блогу

UUID и ULID: что это, отличия и генерация

Zikrasoft · · 7 мин чтения
UUID ULID Веб-разработка JavaScript Базы данных

Каждый раз, когда вы создаёте запись в базе данных, отправляете событие в очередь или генерируете ссылку на ресурс — вам нужен уникальный идентификатор. Auto-increment решает задачу в пределах одной таблицы, но в распределённых системах, микросервисах и API нужен идентификатор, который можно сгенерировать на любом узле без координации. Для этого существуют UUID и ULID — сгенерировать оба можно прямо в браузере через UUID Генератор.

Что такое UUID

UUID (Universally Unique Identifier) — 128-битный идентификатор, записываемый в виде 36 символов: 32 hex-цифры и 4 дефиса.

550e8400-e29b-41d4-a716-446655440000
^^^^^^^^-^^^^-^^^^-^^^^-^^^^^^^^^^^^
   8       4    4    4      12

GUID (Globally Unique Identifier) — это то же самое, просто термин Microsoft. В .NET вы работаете с Guid, в Java — с UUID. Под капотом одна и та же структура.

Вероятность коллизии UUID v4 ничтожно мала: при 2^122 возможных комбинациях нужно сгенерировать около 2.7×10^18 идентификаторов, чтобы вероятность совпадения достигла 50%. На практике коллизий не бывает.

Где UUID используют чаще всего:

  • Первичные ключи в БД — особенно когда данные шардируются между серверами
  • API — идентификаторы ресурсов в REST/GraphQL
  • Микросервисы — корреляция запросов между сервисами (trace id)
  • Идемпотентность — клиент генерирует UUID запроса, сервер отклоняет дубликаты

Версии UUID — какую выбрать

UUID — это не один алгоритм, а семейство версий. Номер версии закодирован в 13-м символе (позиция M):

xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx
              ^
              версия (1, 4, 5, 7...)

UUID v1 — MAC + время

Содержит timestamp и MAC-адрес сетевого интерфейса. Это означает утечку информации: по UUID v1 можно определить, когда и на каком устройстве он создан. В новых проектах использовать не стоит.

UUID v4 — случайный

122 бита чистой случайности. Самый распространённый формат — именно его возвращает crypto.randomUUID() в браузерах и Node.js. Минус: идентификаторы не упорядочены, что приводит к фрагментации B-tree индексов в БД при вставке.

UUID v5 — детерминированный

Генерируется из namespace + имя через SHA-1. Один и тот же вход всегда даёт один и тот же UUID. Полезен, когда нужна стабильная генерация: например, UUID пользователя по email.

import { v5 as uuidv5 } from "uuid";

const NAMESPACE_EMAIL = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";

// Один и тот же email → один и тот же UUID
uuidv5("ivan@example.com", NAMESPACE_EMAIL);
// → всегда 'a6e4eac1-...'

UUID v7 — новый стандарт (RFC 9562)

Принят в 2024 году. Первые 48 бит — Unix-timestamp в миллисекундах, остальные — случайность. UUID v7 сортируемый по времени и совместим с UUID-типами в PostgreSQL, MySQL, SQL Server. Это рекомендация по умолчанию для новых проектов.

Сравнение версий

ВерсияИсточникСортируемыйСтандартКогда использовать
v1MAC + timestampДа*RFC 4122Не рекомендуется (утечка MAC)
v4СлучайностьНетRFC 4122Legacy, широкая совместимость
v5Namespace + SHA-1НетRFC 4122Детерминированная генерация
v7Timestamp + randomДаRFC 9562Новые проекты (рекомендация)

* UUID v1 сортируемый, но байты времени расположены неудобно — для правильной сортировки нужна перестановка.

Что такое ULID

ULID (Universally Unique Lexicographically Sortable Identifier) — альтернатива UUID, разработанная специально для сортируемости и компактности.

01ARZ3NDEKTSV4RRFFQ69G5FAV
|----------|----------------|
 timestamp      randomness
 10 chars        16 chars
 48 бит          80 бит

Формат: 26 символов Crockford Base32 (цифры 0-9 и буквы, исключая I, L, O, U во избежание путаницы). Для сравнения, UUID — 36 символов. ULID экономит 10 символов на каждом идентификаторе.

Разберём реальный ULID:

// ULID: 01HZXK5P00QJZM0VX2RKF8GEJT
//
// Timestamp (первые 10 символов): 01HZXK5P00
// → декодируется в Unix ms timestamp
// → 2024-06-01T12:00:00.000Z
//
// Random (последние 16 символов): QJZM0VX2RKF8GEJT
// → 80 бит криптографической случайности

Ключевое свойство: ULID, созданные позже, всегда лексикографически больше предыдущих. Простое строковое сравнение (>, <, ORDER BY) работает корректно — не нужна специальная логика сортировки.

UUID vs ULID — подробное сравнение

ПараметрUUID v4UUID v7ULID
Длина (строка)36 символов36 символов26 символов
Длина (байты)161616
СортируемыйНетДаДа
ФорматHex + дефисыHex + дефисыCrockford Base32
СтандартRFC 4122RFC 9562Спецификация ULID
Тип в PostgreSQLuuiduuidchar(26) или uuid*
Тип в MySQLBINARY(16) / CHAR(36)BINARY(16) / CHAR(36)BINARY(16) / CHAR(26)
Фрагментация индексовВысокая (случайные вставки)Низкая (последовательные)Низкая (последовательные)

* ULID можно конвертировать в UUID-формат (128 бит совместимы), но это нестандартное использование.

Фрагментация индексов — почему это критично

UUID v4 — полностью случайный. Каждая новая запись вставляется в произвольное место B-tree индекса. При миллионах записей это приводит к:

  • Page splits — страницы индекса постоянно разбиваются
  • Увеличение размера индекса на 20-30%
  • Падение производительности INSERT на нагруженных таблицах

UUID v7 и ULID вставляются последовательно (новые идентификаторы всегда больше предыдущих). Индекс растёт только вправо, как при auto-increment. Разница на больших таблицах (10M+ записей) ощутима.

UUID v7 vs ULID

Оба решают одну задачу — сортируемый уникальный идентификатор. Разница в экосистеме:

  • UUID v7 — стандарт IETF (RFC 9562), нативная поддержка uuid типа в PostgreSQL/MySQL, совместимость со всеми библиотеками UUID
  • ULID — компактнее на 10 символов, удобнее в логах и URL, но требует отдельной библиотеки и не имеет нативного типа в БД

Генерация UUID и ULID в JavaScript

UUID v4 — встроенный метод

// Браузер и Node.js 19+ — ничего устанавливать не нужно
const id = crypto.randomUUID();
// → 'f47ac10b-58cc-4372-a567-0e02b2c3d479'

UUID v7 — библиотека uuid

npm install uuid
import { v7 as uuidv7 } from "uuid";

const id = uuidv7();
// → '019036a0-a58c-7e5b-bb84-3f2a5e148df0'
//    ^^^^^^^^^^^^^^^^ — временная метка
//                     ^^^^^^^^^^^^^^^^^^^^ — случайность

// UUID v7 сортируются хронологически
const ids = Array.from({ length: 5 }, () => uuidv7());
console.log(ids);
// Каждый следующий > предыдущего при строковом сравнении

ULID — библиотека ulid

npm install ulid
import { ulid } from "ulid";

const id = ulid();
// → '01HZXK5P00QJZM0VX2RKF8GEJT'

// Монотонность: ULID в рамках одной миллисекунды
// инкрементирует случайную часть
import { monotonicFactory } from "ulid";
const monotonic = monotonicFactory();

// Гарантированно возрастающие даже при генерации в одну мс
monotonic(); // → '01HZXK5P00QJZM0VX2RKF8GEJT'
monotonic(); // → '01HZXK5P00QJZM0VX2RKF8GEJU' (инкремент)

Не хочется устанавливать библиотеки ради одного идентификатора? UUID Генератор создаёт UUID v4, v7 и ULID прямо в браузере — с копированием в один клик и пакетной генерацией.

Когда что использовать

Выбор зависит от контекста:

UUID v7 — рекомендация по умолчанию. Если начинаете новый проект и нужен уникальный идентификатор для БД — берите v7. Сортируемый, стандартизированный, совместим с uuid типом в PostgreSQL. Не нужно объяснять команде, почему вы выбрали «нестандартный» формат.

UUID v4 — legacy и совместимость. Если существующая система использует v4, нет смысла мигрировать. UUID v4 работает, коллизий не бывает, просто индексы чуть менее эффективны. Также v4 — единственный вариант, если нужна встроенная генерация без зависимостей (crypto.randomUUID()).

ULID — greenfield, логи, компактность. Если 10 символов экономии критичны (логи, URL, мобильные приложения) и вы готовы к тому, что ULID — не стандарт IETF.

Auto-increment — когда не нужна распределённость. Один сервер, одна БД, нет публичного API — обычный SERIAL / BIGSERIAL проще и эффективнее. Не усложняйте архитектуру без причины.

// Резюме выбора в коде
function chooseIdStrategy(context) {
  if (context.distributed || context.publicApi) return "uuid-v7"; // стандарт, сортируемый
  if (context.legacy) return "uuid-v4"; // совместимость
  if (context.compactness) return "ulid"; // короче, сортируемый
  return "auto-increment"; // простота
}

Валидация UUID

Регулярное выражение для проверки UUID любой версии:

const UUID_REGEX =
  /^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

UUID_REGEX.test("550e8400-e29b-41d4-a716-446655440000"); // true (v4)
UUID_REGEX.test("019036a0-a58c-7e5b-bb84-3f2a5e148df0"); // true (v7)
UUID_REGEX.test("not-a-uuid"); // false
UUID_REGEX.test("550e8400-e29b-41d4-a716"); // false (обрезан)

Определение версии — по 13-му символу строки (индекс 14 с учётом дефисов):

function getUuidVersion(uuid) {
  const clean = uuid.replace(/-/g, "");
  const versionChar = clean[12]; // 13-й hex-символ
  const version = parseInt(versionChar, 16);

  if (version >= 1 && version <= 7) return version;
  return null; // не UUID или неизвестная версия
}

getUuidVersion("550e8400-e29b-41d4-a716-446655440000"); // 4
getUuidVersion("019036a0-a58c-7e5b-bb84-3f2a5e148df0"); // 7
getUuidVersion("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); // 1

Для валидации ULID проверяется длина (26 символов) и алфавит Crockford Base32:

const ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/;

ULID_REGEX.test("01HZXK5P00QJZM0VX2RKF8GEJT"); // true
ULID_REGEX.test("01HZXK5P00QJZM0VX2RKF8GEJ"); // false (25 символов)
ULID_REGEX.test("O1HZXK5P00QJZM0VX2RKF8GEJT"); // false (O вместо 0)

Все эти проверки встроены в UUID Генератор — вставьте идентификатор, и инструмент покажет его тип и версию. А если нужно получить хеш произвольных данных (SHA-256, MD5) — посмотрите Генератор хешей.

Итого

UUID v7 — лучший выбор для большинства сценариев в 2026 году: стандартизирован, сортируемый, совместим с существующей инфраструктурой UUID. ULID остаётся отличным вариантом, когда компактность важнее стандартизации. А UUID v4 никуда не денется — он работает и будет работать, просто у v7 объективно больше преимуществ.

Связанные инструменты