[Spring boot] JPA batch insert/update
데이터의 일관성을 위해 웹에서 openAPI로부터 데이터를 받고 그 데이터를 로컬 데이터베이스에 넣는다. 그 후 웹에서 데이터베이스에 데이터를 요청하면 데이터베이스는 그 데이터를 불러오는 경로이다.
데이터를 데이터베이스에 넣는 시간이 생각보다 오래 걸린다. 데이터를 200개만 해도 체감상 1~2분정도 걸리는 것 같다.
로그를 보니 JPA의 saveAll()의 문제로 확인되었다.
한꺼번에 insert되는 것처럼 보이지만 로그를 확인해보면 이런식으로 개별 insert가 진행되기때문에 데이터베이스 부하가 발생한다.
https://www.baeldung.com/spring-data-jpa-batch-inserts
하이버네이트에서는 여러개의 데이터를 한번에 Insert, update하는 Batch기능을 제공한다.
참고로 batch옵션은 Hibernate가 직접 batch insert형식으로 묶어주는 것이 아니라 addBatch해주는 것이다.
Hibernate ORM 5.4.33.Final User Guide
Fetching, essentially, is the process of grabbing data from the database and making it available to the application. Tuning how an application does fetching is one of the biggest factors in determining how an application will perform. Fetching too much dat
docs.jboss.org
공식 문서에 Hibernate disables insert batching at the JDBC level transparently if you use an identity identifier generator. 즉, entity의 식별자(id)생성시 IDENTITY 으로 생성한다면 batch insert를 지원하지 않는다는 문구가 있다.
그 이유는 identity는 데이터베이스에 insert해야 entity @id값이 채워지기 때문에 개별 insert가 필요하다.
jobData.java로 이동해서 GenerationType.IDENTITY를 GenerationType.SEQUENCE 로 바꿔준다.
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
참고로 SEQUENCE는 데이터베이스의 시퀀스를 이용해서 id값을 생성한다.
application.properties
#jpa
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.jdbc.batch_size=20
spring.jpa.properties.hibernate.jdbc.batch_versioned_data = true
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# jpa batch log
spring.jpa.properties.hibernate.generate_statistics=true
- spring.jpa.properties.hibernate.jdbc.batch_size=20
batch 처리가 가능하도록 크기값을 0보다 크게 설정한다.(0 또는 음수는 기능 비활성화임)
- spring.jpa.properties.hibernate.jdbc.batch_versioned_data
일부 JDBC 드라이버는 일괄 처리가 실행될 때 잘못된 행 수를 반환한다. JDBC 드라이버가이 범주에 해당하는 경우이 설정을로 설정해한다.
- spring.jpa.properties.hibernate.order_inserts=true
- spring.jpa.properties.hibernate.order_updates=true
하나의 트랜젝션에 영속성을 가지는 여러 타입이 나타난다면 새로운 batch가 생성되는데 이 때 insert나 update할 때 하나의 쿼리로 묶이지 않는다. 이를 해결하기 위해 추가한다.
- spring.jpa.properties.hibernate.generate_statistics=true
batch 통계 로그를 보기 위해 활성화
insert가 일괄처리 된다.