使用 GenerationType.IDENTITY 时,Spring Batch JPA 批量插入会降低性能

Jef*_*ook 3 spring jpa spring-batch

我正在使用Spring Boot and Spring Batch and JPA将数据从一个数据库加载到另一个数据库中。在我创建的单个批处理作业中,10 steps按顺序运行步骤,每个步骤几乎读取1 millions记录(我无法并行运行,因为我没有并行加载数据)。

我已经使用过GenerationType.IDENTITY并且看起来像因为这个批处理工作花费了很多时间。如果我说加载100 records需要2 min. 目标Postgres database已经sequences由DBA实现了,我们必须遵循这些目标,但是它消耗了所有的性能。

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

如何提高该批处理作业的性能?

我也保留spring.jpa.properties.hibernate.jdbc.batch_size=1000了。chunkSize=1000

Ken*_*han 7

如果实体用于生成其 ID(也在此处的IDENTITY文档中提到),Hibernate 无法批量插入实体。

所以你必须更改为使用SEQUENCE来生成ID。并据此选择使用“pooled”或“pooled-lo”算法从序列中获取新的ID,以通过减少获取ID的往返次数来进一步提高性能。

所以 ID 映射如下所示:

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

和休眠设置:

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.id.optimizer.pooled.preferred = pooled-lo
Run Code Online (Sandbox Code Playgroud)

另外,您必须确保 PostreSQL 中相应的 ID 序列与以下配置对齐@SequenceGenerator

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.id.optimizer.pooled.preferred = pooled-lo
Run Code Online (Sandbox Code Playgroud)

另一个技巧是添加reWriteBatchedInserts=trueJDBC 连接字符串,如文档中所述,这将提供 2-3 倍的性能改进。