Spring JPA - Hibernate: слишком много выполнения пакетной вставки select nextval («последовательность»)

Теперь я пытаюсь повысить производительность своего веб-приложения, использую 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
  • При использовании GenerationType.SEQUENCE / GenerationType.AUTO

    • save(entity):
      • select nextval ('students_id_seq'): execute once
      • insert into ...: выполнить один раз
    • saveAll(n entities):
      • select nextval ('students_id_seq'): execute n times
      • insert into ...: выполнить n / batch_size раз

В заключение, при использовании 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


person Tu Doan    schedule 08.06.2020    source источник


Ответы (1)


Вам нужен алгоритм HiLo для генерации идентификаторов.

Для каждого идентификатора, сгенерированного из последовательности, он генерирует несколько идентификаторов на клиенте без доступа к базе данных.

Вы настраиваете его на своем объекте следующим образом:

    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hilo_sequence_generator")
    @GenericGenerator(
            name = "hilo_sequence_generator",
            strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
            parameters = {
                    @Parameter(name = "sequence_name", value = "hilo_seqeunce"),
                    @Parameter(name = "initial_value", value = "1"),
                    @Parameter(name = "increment_size", value = "3"),
                    @Parameter(name = "optimizer", value = "hilo")
            })
    @Id
    private Long id;
person Jens Schauder    schedule 08.06.2020
comment
попробовал hiLo с mysql и весенней загрузкой, он по-прежнему создает последовательность в db и обновляет слишком много select next_val - person Shubham Debnath; 11.01.2021