UUID и ULID: что это, отличия и генерация
Каждый раз, когда вы создаёте запись в базе данных, отправляете событие в очередь или генерируете ссылку на ресурс — вам нужен уникальный идентификатор. 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. Это рекомендация по умолчанию для новых проектов.
Сравнение версий
| Версия | Источник | Сортируемый | Стандарт | Когда использовать |
|---|---|---|---|---|
| v1 | MAC + timestamp | Да* | RFC 4122 | Не рекомендуется (утечка MAC) |
| v4 | Случайность | Нет | RFC 4122 | Legacy, широкая совместимость |
| v5 | Namespace + SHA-1 | Нет | RFC 4122 | Детерминированная генерация |
| v7 | Timestamp + 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 v4 | UUID v7 | ULID |
|---|---|---|---|
| Длина (строка) | 36 символов | 36 символов | 26 символов |
| Длина (байты) | 16 | 16 | 16 |
| Сортируемый | Нет | Да | Да |
| Формат | Hex + дефисы | Hex + дефисы | Crockford Base32 |
| Стандарт | RFC 4122 | RFC 9562 | Спецификация ULID |
| Тип в PostgreSQL | uuid | uuid | char(26) или uuid* |
| Тип в MySQL | BINARY(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 объективно больше преимуществ.