문제상황 : 대용량 데이터를 insert 시에 쿼리의 호출수가 데이터의 개수만큼 쿼리가 날라가기에 성능 저하, 요금 청구에 문제가 될 수 있다고 판단하였다. 때문에 insert 쿼리수를 줄일 수 있는 방법을 찾고 자 하였다.
bulk insert 쿼리를 이용하면 한번의 쿼리로 여러건의 데이터를 한번에 insert 할 수 있기 때문에, 데이터베이스와 어플리케이션 사이의 통신에 들어가는 비용을 줄여주어 성능상 이득을 얻을 수 있다.
하지만 bulk insert를 원하는 테이블에서 auto_increment를 사용하고 있다면 bulk insert는 JPA를 통해서는 해결할 수 없다.
spring:
jpa:
database: mysql
properties:
hibernate.jdbc.batch_size: 50 (10 ~ 1000)
hibernate.order_inserts: true
hibernate.order_updates: true
hibernate.dialect: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql: true
datasource:
url: jdbc:mysql://localhost:3366/batch_study?useSSL=false&serverTimezone=UTC&autoReconnect=true&rewriteBatchedStatements=true
driver-class-name: com.mysql.cj.jdbc.Driver
위의 두 기능 모두 GenerationType.IDENTITY의 경우에는 Batch Insert가 진행되지 않습니다.
Sequence, table 방식을 조치 없이 사용하면 Batch Insert를 쓰더라도 IDENTITY 방식보다 더 느리다고 한다.
->https://homoefficio.github.io/2020/01/25/Spring-Data에서-Batch-Insert-최적화/
Spring Data JPA(구현체 : Hibernate) 대신 Spring Data JDBC 사용하기
JdbcTemplate.batchUpdate() 라는 메서드안의 Overloading 되어 있는 편리 메서드를 골라 사용가능하다, 여기서는 batch 크기를 지정할 수 있는 아래의 메서드를 구현한다.
batchUpdate(String sql, BatchPreparedStatementSetter pss)
실행을 해보면 GenerationType 이 IDENTITY여서 찍히는 로그에서는 개별 INSERT가 날라가지만 실제로는 BATCH INSERT 가 된다.
♦️주의 : Hibernate는 드라이버에 여러 개의 삽입 문을 보내고 드라이버는 이를 다시 작성합니다. 따라서 Hibernate 로그는 드라이버가 데이터베이스에 보낸 SQL이 아니라 Hibernate가 드라이버에 보낸 SQL만 보여줍니다.
→ 때문에 드라이버에서 DB로 날라가는 쿼리를 확인하려면 아래 사이트를 활용하여 설정을 해주어야 한다.
application.yml 설정 방식은 다음 블로그를 참고하자