ULID — 26 символов Crockford Base32: первые 10 — время в миллисекундах, остальные 16 — 80 случайных бит. Строки сортируются в порядке создания, как UUID v7, а алфавит без I, L, O и U не путается при чтении вслух и переписывании руками.
Ключ, который удобно сортировать по самому значению, — события, журналы, очереди.
Там, где 36 символов UUID длинны, а время внутри нужно.
Если база хранит идентификаторы в колонке uuid — лучше v7: ULID туда без перевода не ляжет.
Чем отличается от соседей
Против UUID v7: устроены почти одинаково — 48 бит времени впереди и случайность после, — но v7 стандартизован в RFC 9562, а ULID — отдельная спецификация. ULID короче в записи (26 против 36) и читается без путаницы букв. Против NanoID: ULID сортируется и раскрывает время создания, NanoID — нет. Наш генератор монотонен: пачка внутри одной миллисекунды идёт по возрастанию.
ULID — 26 символов Crockford Base32, первые десять из которых — время в миллисекундах, поэтому значения сортируются по созданию. UUID v4 — 36 символов и случайный порядок, UUID v7 устроен как ULID, но записан шестнадцатерично и стандартизован в RFC 9562. Оба формата занимают 128 бит, отличаются запись и наличие стандарта.
Первые десять символов — 48 бит времени в Crockford Base32: каждый символ — пять бит, старшие впереди. Переведите их в число миллисекунд от 1 января 1970 года — получите момент создания: 01ARYZ6S41 — это 30 июля 2016 года, 22:36:16 UTC. Остальные шестнадцать символов — случайная часть, времени в ней нет.
Это алфавит Crockford Base32: из него убраны I и L, которые путают с единицей, O, который путают с нулём, и U — чтобы случайно не складывались неприличные слова. При разборе многие реализации принимают I и L как 1, O как 0 и не различают регистр. Поэтому ULID легко продиктовать и переписать руками.
Двоичное значение — да: и ULID, и UUID занимают 128 бит, и многие библиотеки умеют переводить одно в другое. Но получится UUID без правильных битов версии и варианта, и строгие проверки назовут его нестандартным. Строку из 26 символов колонка uuid не примет. Если нужен стандартный тип и сортировка — берите сразу UUID v7.
Если случайная часть каждый раз новая — нет, порядок внутри миллисекунды случаен. Спецификация ULID описывает монотонный режим: в той же миллисекунде случайная часть увеличивается на единицу. Наш генератор работает именно так, поэтому пачка из пятидесяти значений, выпущенная за одну миллисекунду, идёт строго по возрастанию.
Время в ULID — 48 бит миллисекунд от 1970 года, их хватит до 10889 года: так и пишет спецификация. Поэтому первый символ ULID не бывает больше 7 — старшие биты пока нулевые. Строка с первым символом 8 и выше — не ULID, и разбор времени её не примет.