Генератор UUID · форматUUID v7 — генератор и как он устроен
Седьмая версия начинается с времени создания в миллисекундах, дальше идут 74 случайных бита. Поэтому значения сортируются в порядке создания и вставляются в конец индекса — это и сделало v7 рекомендуемым первичным ключом. Стандартизована в RFC 9562 в 2024 году.
Первичный ключ большой таблицы: вставки идут в конец индекса, страницы не дробятся.
Идентификатор событий и журналов, которые удобно сортировать по самому ID.
Замена v1 и v6, когда нужно время внутри, но без адреса машины.
Чем отличается от соседей
Против v4: v7 упорядочен и бережёт индекс, но выдаёт момент создания с точностью до миллисекунды — для публичных ссылок это может быть лишним. Против ULID: оба сортируются по времени и устроены почти одинаково (48 бит времени впереди), но v7 — стандарт RFC и ложится в колонку uuid, а ULID короче в записи — 26 знаков вместо 36. Наш генератор в пачке монотонен: внутри миллисекунды случайная часть растёт на единицу.
Первые двенадцать шестнадцатеричных цифр, без дефиса, — это Unix-время в миллисекундах. Переведите их в десятичное число и получите момент создания: 017f22e279b0 — это 22 февраля 2022 года, 19:22:22 UTC. Поле «Проверка» на странице генератора делает это само и показывает дату, время и сколько дней прошло с создания идентификатора.
Да, с точностью до миллисекунды, и это не обойти: время — часть формата. Для внутренних ключей это обычно не важно, а для публичных ссылок может быть лишним — по ним видно, когда зарегистрирован пользователь или создан документ. В таких местах берут v4 или показывают наружу отдельный случайный идентификатор, оставив v7 ключом внутри базы.
Да, с 18-й версии в PostgreSQL есть встроенная функция uuidv7(). В более старых версиях значения генерируют в приложении или расширением, а хранят в обычной колонке типа uuid — тип не проверяет версию, ему всё равно, какая из восьми записана. Переход с v4 на v7 поэтому не требует менять схему таблицы.
Не обязательно: если младшие биты случайны, порядок внутри одной миллисекунды случаен. RFC 9562 описывает способы это исправить — счётчик в части rand_a или приращение случайной части. Наш генератор использует второй: внутри миллисекунды значение растёт на единицу, поэтому пачка из пятидесяти UUID идёт строго по возрастанию.
Если база хранит ключи в колонке uuid, — v7: он стандартизован в RFC 9562 и ложится туда без преобразований, а ULID придётся переводить. Если ключ хранится строкой и важна краткость, — ULID: 26 символов против 36. По устройству они почти одинаковы: 48 бит времени впереди и случайность после, обе сортируются по созданию.
Время занимает 48 бит в миллисекундах от 1 января 1970 года, и их хватит до 10889 года. Ближе проблема другая — часы машины: если они отстают или их переводят назад, новые значения окажутся меньше старых. Генераторы с монотонным режимом, как этот, сглаживают обратный скачок, продолжая счёт от последнего выданного значения.