반응형
- Spring Boot, Spring Data JPA, PostgreSQL 환경에서 대량 데이터를 삽입할 때 사용할 수 있는 여러 방법의 성능을 비교
- 개별 엔티티 저장(
Repository.save()
) - 엔티티 컬렉션 저장(
Repository.saveAll()
) - JDBC 템플릿을 활용한 배치 삽입 (
batchInsert()
)
- 개별 엔티티 저장(
- PostgreSQL JDBC 드라이버의
reWriteBatchedInserts
옵션과 배치 크기의 영향
엔티티와 데이터를 저장하는 메서드는 다음과 같다. ID 생성 전략을 IDENTITY
로 설정하면 batch 옵션이 동작하지 않으므로 주의해야 한다.
@Entity
@SequenceGenerator(
name = "issued_coupon_code_gen",
sequenceName = "issued_coupon_code_coupon_code_sn_seq",
initialValue = 1,
allocationSize = 100
)
public class IssuedCouponCode {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "issued_coupon_code_gen")
private Long couponCodeSn;
private String serialCode;
}
@Transactional
public void save(int size) {
List<IssuedCouponCode> issuedCouponCodes = generateList(size);
issuedCouponCodes.forEach(issuedCouponCodeRepository::save);
}
@Transactional
public void saveAll(int size) {
List<IssuedCouponCode> issuedCouponCodes = generateList(size);
issuedCouponCodeRepository.saveAll(issuedCouponCodes);
}
@Transactional
public void batchInsert(int size) {
List<IssuedCouponCode> issuedCouponCodes = generateList(size);
issuedCouponCodeRepository.batchInsert(issuedCouponCodes);
}
hibernate.jdbc.batch_size
를 100으로 설정 후 10만건의 데이터를 추가하는데 걸리는 시간을 측정했다.
삽입 방식 | reWriteBatchedInserts=false | reWriteBatchedInserts=true | 성능 향상 |
---|---|---|---|
save() | 6524ms | 5513ms | 15.5% |
saveAll | 5062ms | 3498ms | 30.9% |
batchInsert | 2537ms | 601ms | 76.3% |
saveAll()
이save()
보다 더 좋은 성능을 보였다.- 모든 설정에서 JDBC 템플릿을 직접 사용해 배치 삽입을 수행하는게 가장 성능이 좋았다. → Jpa Repository를 사용할 때 발생하는 엔티티 관리와 캐싱 오버헤드 때문
reWriteBatchedInserts=true
설정이 전체적으로 성능을 향상시켰다.
PostgreSQL JDBC 드라이버의 reWriteBatchedInserts
가 배치 삽입 쿼리의 성능에 상당한 영향을 주는 것을 확인할 수 있었다. true
로 설정할 경우 여러 개별 삽입 문을 하나의 다중 행 삽입 문으로 만들어 준다.
-- reWriteBatchedInserts=false
INSERT INTO issued_coupon_code(serial_code) VALUES('1');
INSERT INTO issued_coupon_code(serial_code) VALUES('2');
INSERT INTO issued_coupon_code(serial_code) VALUES('3');
-- reWriteBatchedInserts=true
INSERT INTO issued_coupon_code(serial_code) VALUES('1'),('2'),('3');
성능이 중요한 대량 처리 로직에서는 JPA Repository를 사용하는 것 대신 JDBC 기반의 batchInsert() 방식을 선택하는 것이 최적의 선택일 수 있다.
반응형