Вопрос про integer / bigint или UUID всегда был. Оба подхода встречаются на практике.
Годами integer / bigint часто выбирали для PK (Primary Key) ради производительности.
А UUIDv4 выбирали, когда важна уникальность id на огромных объемах данных.
Но с UUIDv7 старое правило стоит пересмотреть 👇
👉 Почему integer был быстрее
Дело было в индексации.
Индекс — это как алфавитный указатель в книге: чтобы найти нужную запись, БД не перебирает миллион строк подряд, а использует отдельную упорядоченную структуру дерева.
▫️ Если id (PK) генерируется последовательно:
1 → 2 → 3 → 4 → ...
новые значения обычно попадают в правую часть B-tree индекса — дерева, в котором значения хранятся в отсортированном виде и разбиваются по диапазонам между узлами.
Поэтому БД в основном работает с одной и той же крайней областью индекса, а не вставляет записи в случайные места по всему дереву.
Такие вставки предсказуемы и хорошо сохраняют локальность данных.
▫️ А теперь UUIDv4:
a3f8b2c1-91c2-4b7e-8f3a-6d2e9c1b7a4f
Он генерируется случайно. Ни алфавитного, ни цифрового порядка.
Следующий UUID может попасть в совершенно другую часть диапазона индекса.
В результате вставки затрагивают разные страницы B-tree, хуже используют кэш и могут чаще приводить к разрыву страниц.
На больших таблицах и при интенсивной записи данных в БД это уже имеет значение.
Поэтому UUID обычно особенно полезен там, где идентификатор нужно генерировать независимо:
✔️ делать гарантированно уникальным
✔️ в нескольких микросервисах
✔️ на разных узлах
✔️ на клиенте
✔️ без общей последовательности в одной БД
👉 Что изменилось
Почти год назад PostgreSQL 18 добавил встроенную функцию:
uuidv7()
UUIDv7 — уже не случайный UUIDv4.
В его старших битах хранится время генерации.
Поэтому значения получаются упорядоченными примерно по времени создания и новые UUID чаще оказываются рядом друг с другом в индексе B-tree.
👉 То есть один из главных недостатков UUIDv4 — хаотичные вставки по всему индексу — существенно уменьшается с приходом UUIDv7.
Так что теперь UUIDv7 можно гораздо смелее рассматривать как PK для новых таблиц, особенно в распределённых системах с сервисами и микросервисами.
Но это не значит, что bigint больше не нужен.
📌 При выборе типа данных для id (PK) всё ещё надо учитывать минимум 3 вещи:
1️⃣ Размер
integer — 4 байта
bigint — 8 байт
uuid — 16 байт
И дело не только в самой таблице.
PK потом становится FK в других таблицах, попадает в индексы — и объем данных начинает множиться.
2️⃣ Способ генерации ID
Если у нас одна БД и централизованная генерация идентификаторов в одной БД — bigint может быть отличным вариантом.
Если ID должны независимо создавать несколько микросервисов — UUID становится намного удобнее.
3️⃣ Приватность
UUIDv7 «помнит» время.
Если такой ID передаётся наружу:
/orders/{uuid}
/users/{uuid}
/payments/{uuid}
из него можно определить примерное время создания объекта.
Для некоторых систем это нежелательная утечка метаданных.
💡 Поэтому UUIDv7 не делает bigint устаревшим.
Но убирает один из главных аргументов против UUID — хаотичные вставки UUIDv4 в B-tree.
А что сейчас используете в своих проектах для PK: bigint, UUIDv4 или уже UUIDv7? 👇
#БД_и_SQL_GA
📱 Tg | 💙 ВК | 💬 Max
