문제
카드 이미지를 기존 jpaRepository.saveAll 하는 과정에서 insert 쿼리가 다음과 같이 image url의 갯수만큼 나간다.
insert
into
card_images
(created_date, modified_date, card_id, image_url)
values
(?, ?, ?, ?)
Hibernate:
insert
into
card_images
(created_date, modified_date, card_id, image_url)
values
(?, ?, ?, ?
한번의 쿼리만 나갈 수 있는 방법이 없을까?
Batch insert
INSERT INTO table (col1, col2) VALUES
(val1, val11),
(val2, val22),
(val3, val33);
하나의 트랜잭션으로 묶이기에 다음과 같은 하나의 쿼리문으로 수행한다. 개별적인 insert 쿼리 문의 경우 쿼리를 던지고 응답을 받아야 다음 쿼리를 진행하기에 성능이 좋지 않다.
Batch insert는 이런 점에서 성능이 훨씬 좋다.
그러나 이번 프로젝트에서는 JPA + MySQL 을 사용하여, IDENTITY 전략을 채택하고 있기에 Batch insert 가 불가능하다.
JDBCTemplate을 이용하자
하지만 JPA, 기존 테이블 전략을 그대로 가지고 가면서도 부분적으로 JDBC를 적용하여 Batch Insert를 수행할 수 있다.
JDBCTemplate의 Batch를 지원하는 batchUpdate() 메서드를 이용하면 된다.
application-local.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/nabitest?&rewriteBatchedStatements=true
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
rewriteBatchedStatesments=true를 설정해준다.
코드
@Repository
@RequiredArgsConstructor
public class CardImageBulkRepository {
private final JdbcTemplate jdbcTemplate;
@Transactional
public void saveAll(List<CardImage> cardImages) {
String sql = "INSERT INTO card_images (created_date, modified_date, image_url, card_id) VALUES (?, ?, ?, ?)";
jdbcTemplate.batchUpdate(sql,
cardImages,
cardImages.size(),
(PreparedStatement ps, CardImage cardImage) -> {
ps.setTimestamp(1, cardImage.getCreatedDate() != null ? Timestamp.valueOf(cardImage.getCreatedDate()) : null);
ps.setTimestamp(2, cardImage.getModifiedDate() != null ? Timestamp.valueOf(cardImage.getModifiedDate()) : null);
ps.setString(3, cardImage.getImageUrl());
ps.setLong(4,cardImage.getCard().getCardId());
});
}
}
https://www.baeldung.com/spring-jdbc-batch-inserts 해당 공식 문서를 참고하여 작성해보았다.
결과
INSERT INTO card_images (created_date, modified_date, image_url, card_id)
VALUES ('2023-11-15T21:00:34.000+0900', '2023-11-15T21:00:34.000+0900', '썸네일이미지입니다요', 1),(null, null, 'string', 1)
다음과 같이 쿼리가 한번에 나가는것을 확인 가능하다.
'개발 일지 > 프로젝트' 카테고리의 다른 글
인덱싱을 적용한 tps 속도 개선 (0) | 2024.02.06 |
---|---|
swagger api 에러 상세히 내려주게 커스텀하기 (0) | 2024.02.04 |
멀티모듈 적용기 (의존성, POJO 분리까지) (0) | 2024.02.04 |