JPA에서 bulk insert 하기 (JPA batch insert)

TaeYeong Jeong·2022년 6월 13일
0

mysql General log 확인하기

만약 general_logfalse라면 SET GLOBAL general_log = ON;을 사용해 ON으로 바꿔준다.

그 다음 로그를 저장할 위치를 정해준다.

명령어는 SET GLOBAL general_log_file = ~~~

그 다음 지정한 위치로 가서 파일을 열어보면 로그를 확인할 수 있다.

mysql bulk insert

먼저 build.gradle dependencies에 mysql을 추가한다.

build.gradle 새로고침 후 application.yml에서 datasource를 작성한다.

이때 rewriteBatchedStatements 옵션을 true로 해주어야 한다.

그리고 spring.jpa.properties.hibernate.jdbc.batch_size 속성을 원하는 만큼 지정해준다. (최대 1000)

insert 할 때는 spring.jpa.properties.hibernate.default_batch_fetch_size 속성에 batch size를 지정해주면 됐는데 insert는 jdbc.batch_size 속성을 사용해야 하는 것 같다.

bulk insert는 id가 IDENTITY일 경우 적용되지 않는다고 해서 SEQUENCE로 적용했다.

batch size를 1000으로 한 결과 18~20초 정도가 소요되었다.

bulk insert가 되었는데도 이렇게 시간이 오래 걸리면 일반적인 경우에는 얼마나 시간이 걸릴지 궁금해서 한 번 테스트 해보았다.

(strategy = GenerationType.SEQUENCE)를 제거해 MySQL의 기본전략으로 변경했다. 그런데 SEQUENCE로 설정했을 때와 같이 bulk insert 되었고, 소요 시간도 비슷하게 나왔다.

MySQL의 기본 전략은 auto_increment라 IDENTITY일 줄 알았는데 찾아보니 strategy = GenerationType.AUTO)로 설정하면 TABLE 전략이 된다고 한다.

그래서 (strategy = GenerationType.IDENTITY)라고 명확하게 작성하고 실행해보았다.

그랬더니 이렇게 insert 쿼리가 따로 나가는 것을 확인할 수 있었는데, 아까의 절반 정도인 7~9초 정도밖에 걸리지 않았다.

이유를 찾아봤는데 원래 MySQL의 경우에는 IDENTITY 방식이 빠르다고 한다.

  • MySQL에는 SEQUENCE가 없으므로 AUTO로 지정해도 실제로는 TABLE 방식으로 동작한다.
  • AUTO 방식에서는 batch insert가 실행됨에도 불구하고 채번 부하가 상당히 커서, batch insert가 실행되지 못하는 IDENTITY 방식보다 느리다.
  • 특히 insert 하려는 데이터 row 수가 커넥션 풀에 있는 커넥션보다 많다면, 해당 테이블의 auto_increment 키 값은 IDENTITY 방식으로 생성하는 것이 좋다.

다른 DB에서는 다른 결과가 나올 수 있다.

Reference

https://github.com/HomoEfficio/dev-tips/blob/master/JPA-GenerationType-%EB%B3%84-INSERT-%EC%84%B1%EB%8A%A5-%EB%B9%84%EA%B5%90.md

0개의 댓글