Стратегии генерации ID
@GeneratedValue решает, как именно генерируется значение первичного ключа — есть несколько стратегий, и выбор влияет на производительность.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
| Стратегия | Как работает |
|---|---|
IDENTITY | база сама генерирует id при вставке (auto-increment) |
SEQUENCE | отдельный объект-последовательность в базе, Hibernate запрашивает следующее значение |
TABLE | отдельная служебная таблица хранит счётчики (медленно, используется редко) |
AUTO | Hibernate сам выбирает подходящую стратегию под конкретную СУБД |
Копнуть глубже
IDENTITY мешает батчевой вставке. При IDENTITY Hibernate обязан выполнить INSERT сразу, чтобы узнать сгенерированный id (он нужен для связей с другими объектами) — это не даёт собрать несколько вставок в один пакетный запрос (batch), и каждая вставка идёт отдельным обращением к базе, что медленнее на больших объёмах.
SEQUENCE лучше для производительности, потому что Hibernate может запросить сразу несколько значений последовательности заранее (allocationSize) и использовать их для пакетной вставки, не дёргая базу на каждый INSERT:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
@SequenceGenerator(name = "user_seq", sequenceName = "user_id_seq", allocationSize = 50)
private Long id;
PostgreSQL поддерживает оба варианта — SEQUENCE обычно предпочтительнее в высоконагруженных приложениях с частыми массовыми вставками.
• почему IDENTITY мешает батчевой вставке, а SEQUENCE — нет (если дошёл до 2-го слоя).