Зачем нужен первичный ключ?
Что проверяют
Понимаете ли вы, что первичный ключ это не формальность для ORM, а ограничение, от которого зависят связи, индексы и даже репликация. Следом обычно спрашивают, что выбрать: автоинкремент, UUID или естественный ключ.
Как отвечать
Первичный ключ однозначно идентифицирует строку. Технически это NOT NULL плюс UNIQUE, в таблице он один, но может быть составным. Зачем он нужен:
- адресация строки:
UPDATEиDELETEпо ключу затрагивают ровно одну строку; - индекс: база сама создаёт уникальный индекс. В PostgreSQL это обычный B-tree, а в MySQL с InnoDB таблица физически хранится упорядоченной по ключу, поэтому его выбор влияет на скорость вставки;
- связи: на него ссылаются внешние ключи других таблиц;
- репликация: логическая репликация PostgreSQL по умолчанию опознаёт строки по первичному ключу, и без него
UPDATEиDELETEна опубликованной таблице завершатся ошибкой. CDC вроде Debezium тоже на него опирается.
Дальше про выбор ключа:
- суррогатный целочисленный:
bigint GENERATED ALWAYS AS IDENTITY, компактный и быстрый, но выдаёт объём данных и мешает сливать записи из разных баз; - UUID: генерируется в приложении, удобен в распределённой системе. Случайный UUIDv4 разбрасывает вставки по индексу, поэтому лучше упорядоченный по времени UUIDv7. В Go его даёт
uuid.NewV7()изgithub.com/google/uuid, в PostgreSQL 18 есть функцияuuidv7(); - естественный: ИНН, email, номер документа. Выглядит логично, пока значение не придётся поменять.
Со стороны Go полезно помнить: драйверы PostgreSQL не поддерживают LastInsertId, id получают через INSERT ... RETURNING id, а повторную вставку делают идемпотентной через ON CONFLICT (id) DO NOTHING.
Где спотыкаются
Думают, что суррогатный ключ защищает от дублей. Два пользователя с одним email и разными id запишутся спокойно, нужно отдельное уникальное ограничение на email.
Берут естественный ключ, а потом он меняется, и приходится каскадно обновлять все ссылающиеся таблицы.
Ставят integer вместо bigint для растущей таблицы. Предел около 2,1 миллиарда кажется недостижимым, пока вставки не начнут падать с ошибкой переполнения.