Начинаем новый сервис с нуля, Rails 8.1, PostgreSQL 18. В команде спор: одни хотят UUID везде, чтобы id не светились в адресах и их можно было генерировать на клиенте, другие говорят, что bigint проще и быстрее. Кто что выбрал и не пожалел через пару лет?
Я за bigint внутри и отдельный публичный идентификатор наружу, если надо прятать. Случайный UUIDv4 как первичный ключ плох для B-tree: вставки летят в случайные места индекса, страницы постоянно делятся, кэш используется хуже. Если всё-таки UUID, то упорядоченный по времени, седьмой версии. В 18-м для него появилась встроенная uuidv7(), раньше генерировали в приложении:
create_table :orders, id: :uuid, default: -> { "uuidv7()" } do |t|
t.references :account, type: :uuid, null: false, foreign_key: true
t.timestamps
end
И сразу пропишите в генераторах g.orm :active_record, primary_key_type: :uuid, иначе через месяц кто-нибудь создаст таблицу с bigint и внешним ключом не того типа.
Цифры для спора. Я как-то наливал по 10 млн строк в две таблицы на 16-м: индекс первичного ключа на bigint вышел 214 МБ, на UUIDv4 около 390 МБ, и вставка на UUIDv4 к концу стала медленнее раза в полтора, когда индекс перестал помещаться в shared_buffers. UUIDv7 по скорости вставки почти как bigint, по размеру как UUID. И внешние ключи тоже вырастают вдвое, это часто забывают посчитать.
мы в Hanami взяли UUIDv7 и генерируем в приложении, полёт нормальный. главное, чтобы все сервисы генерировали одной версией