문제상황 : 대용량 데이터를 insert 시에 쿼리의 호출수가 데이터의 개수만큼 쿼리가 날라가기에 성능 저하, 요금 청구에 문제가 될 수 있다고 판단하였다. 때문에 insert 쿼리수를 줄일 수 있는 방법을 찾고 자 하였다.

  1. Bulk Insert

bulk insert 쿼리를 이용하면 한번의 쿼리로 여러건의 데이터를 한번에 insert 할 수 있기 때문에, 데이터베이스와 어플리케이션 사이의 통신에 들어가는 비용을 줄여주어 성능상 이득을 얻을 수 있다.

하지만 bulk insert를 원하는 테이블에서 auto_increment를 사용하고 있다면 bulk insert는 JPA를 통해서는 해결할 수 없다.

  1. Batch Insert With 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가 진행되지 않습니다.

  1. Sequence나 Table 방식을 사용하면서 채번 부하를 낮추기

Sequence, table 방식을 조치 없이 사용하면 Batch Insert를 쓰더라도 IDENTITY 방식보다 더 느리다고 한다.

->https://homoefficio.github.io/2020/01/25/Spring-Data에서-Batch-Insert-최적화/

  1. 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 설정 방식은 다음 블로그를 참고하자

    https://techblog.woowahan.com/2695/