Теперь я пытаюсь повысить производительность своего веб-приложения, использую spring JPA 2.3.0- Hibernate 5.4.15.Final, Postgres 12 и управляю транзакцией с помощью @Transaction. Веб-приложение развертывается на aws beanstalk, запускает несколько экземпляров одновременно, но экземпляр базы данных не масштабируется. А для ID таблиц я использую тип bigSerial.
Например, у меня есть таблица STUDENTS, ID - bigSerial и некоторые другие столбцы. У меня проблемы при использовании
@GeneratedValue(strategy = GenerationType.IDENTITY)
, Hibernate не смог выполнить пакетную вставку при сохранении списка объектов. И я пытаюсь использовать
@GeneratedValue(strategy = GenerationType.AUTO, generator = "students_id_seq")
@SequenceGenerator(name = "students_id_seq", sequenceName = "students_id_seq")
hibernate.id.new_generator_mappings=false
hibernate.jdbc.batch_size=10
hibernate.order_inserts=true
hibernate.order_updates=true
hibernate.batch_versioned_data=true
Кажется, что Hibernate может выполнять пакетную вставку, но проблема в том, что Hibernate выполняет select nextval ('students_id_seq')
несколько раз. Если список сущностей содержит 30 элементов, Hibernate выполняет select nextval
30 раз и 3 раза для запроса пакетной вставки.
Немного статистики:
При использовании GenerationType.IDENTITY
- save(entity):
insert into ...
: execute once
- saveAll(n entities)
insert into ...
: execute n times
- save(entity):
При использовании GenerationType.SEQUENCE / GenerationType.AUTO
- save(entity):
select nextval ('students_id_seq')
: execute onceinsert into ...
: выполнить один раз
- saveAll(n entities):
select nextval ('students_id_seq')
: execute n timesinsert into ...
: выполнить n / batch_size раз
- save(entity):
В заключение, при использовании GenerationType.AUTO
или GenerationType.SEQUENCE
с allocationSize = 1
:
- при вставке одного объекта приложение увеличивается в 100% раз для выполнения запросов (от одного запроса вставки увеличивается только до 2 запросов: выберите следующее значение и вставьте запрос)
- при пакетной вставке приложение увеличивается более чем на 10%, если batch_size = 10
Мой вопрос: есть ли способ пакетной вставки, но не выполнения для многих select nextval
запросов? Что-то вроде GenerationType.IDENTITY
, а не выполнения select nextval
, просто пакетная вставка, и идентификаторы будут обрабатываться по порядку в базе данных.
Когда я тестирую с GenerationType.SEQUENCE
и allocationSize=1
(GenerationType.AUTO)
, приложение выполняет слишком много select nextval
запросов, я думаю, что это даже хуже, чем стратегия IDENTITY. И по некоторым причинам я не хочу использовать allocationSize
, это может привести к дублированию ошибки первичного ключа при выполнении вручную запроса вставки или при переносе данных или в некоторых других случаях.
После некоторого исследования я нашел способ получить список значений последовательности:
select nextval ('students_id_seq') from generate_series(1,10);
Мы можем заменить 10 на entityList.size (), или количество сущностей не имеет идентификатора в entityList при пакетной вставке, просто получите достаточно для использования, не создавайте слишком большого промежутка между идентификаторами, но я не уверен, что или не поддерживается Hibernate, если да, поделитесь справочной документацией.
Спасибо
https://discourse.hibernate.org/t/batch-insert-execute-too-much-select-nextval-sequence/4232