Spring Batch JPA Bulk Insert снижает производительность при использовании GenerationType.IDENTITY - PullRequest
0 голосов
/ 16 июня 2020

Я использую Spring Boot and Spring Batch and JPA для загрузки данных из одной базы данных в другую. В одном пакетном задании я создал 10 steps для последовательного выполнения шагов, и каждый шаг читает почти 1 millions записей (я не могу работать параллельно, потому что данные, которые я не загружаю параллельно).

Я использовал GenerationType.IDENTITY и выгляжу так, потому что это пакетное задание отнимает чертовски много времени. Если я скажу загрузить 100 records, потребуется 2 min. Целевой объект Postgres database имеет sequences, реализованный администратором баз данных, и мы должны следовать ему, но он съедает всю производительность.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "EMP_ID", nullable = false, updatable = false, insertable = false)
private Long id;

Как я могу улучшить производительность этого пакетного задания?

Я оставил spring.jpa.properties.hibernate.jdbc.batch_size=1000 и chunkSize=1000.

Ответы [ 2 ]

2 голосов
/ 16 июня 2020

Hibernate не может выполнять пакетную вставку сущностей, если сущность использует IDENTITY для генерации своего идентификатора (также упоминается в документации по адресу здесь ).

Поэтому вам нужно изменить использование SEQUENCE для генерации идентификатора. И согласно this , выберите использование алгоритма «объединенный» или «объединенный-лоу» для получения нового идентификатора из последовательности, чтобы еще больше повысить производительность за счет сокращения количества циклов обработки для получения идентификатора.

Таким образом, сопоставление идентификаторов выглядит так:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="foo_sequence")
@SequenceGenerator(name="emp_sequence", sequenceName = "emp_id_seq", allocationSize = 100)
private Long id;

И настройки гибернации:

spring.jpa.properties.hibernate.order_inserts = true
spring.jpa.properties.hibernate.order_updates = true
spring.jpa.properties.hibernate.jdbc.batch_size = 1000
spring.jpa.properties.hibernate.jdbc.batch_versioned_data = true


# For using "pool-lo" optimiser for generating ID when using JPA @SequenceGenerator
spring.jpa.properties.hibernate.hibernate.id.optimizer.pooled.preferred = pooled-lo

Кроме того, вы должны убедиться, что соответствующая последовательность идентификаторов в Postre SQL совпадает с конфигурацией в @SequenceGenerator:

alter sequence emp_id_seq increment by 100;

Еще один совет - добавить reWriteBatchedInserts=true в строку подключения JDB C, что обеспечит увеличение производительности в 2-3 раза, как указано в документы .

0 голосов
/ 16 июня 2020

Я Джефф

В прошлом году мы с моей командой столкнулись с ситуацией, когда выполнение операций записи в БД занимало целую вечность.

Для повышения производительности мы сделали следующее:

  • Используйте репозитории и управляемые объекты только для операций чтения из БД, но никогда не изменяйте эти объекты, чтобы избежать Spring jpa для записи изменений в базу данных .
  • Создайте процедуру сохранения для операции вставки / обновления.
  • Вызовите SP с помощью JDBCBatchItemWriter, используя параметры индекса
  • Установите параметры с помощью ItemPreparedStatementSetter

Таким образом мы сможем улучшить производительность, уменьшив количество обращений к БД!

Надеюсь, это поможет

...