프로젝트를 하면서 데이터를 저장하는 부분을 구현하고 있었습니다. CrudRepository에는 Iterable을 input으로 여러 tuple을 저장하는 메서드인 saveAll을 제공하고 있습니다. 그런데 제가 구현하는 부분에서는 loop에서 여러 tuple을 save로 저장하고 싶었습니다. 두 메서드의 속도에 차이가 있을까요?
save가 오래걸리지 않을까?
저는 단순하게 여러번 쿼리를 날리는 것보다 한 번 쿼리를 날리는 것이 더 시간이 덜 소요될 것이라 생각했습니다. 예를 들어 100개의 tuple을 저장해야한다고 했을 때, save 메서드로 tuple 하나마다 데이터베이스에 요청을 날리면, 데이터베이스는 쿼리가 올 때마다 해당 데이터를 저장하기위해 저장장치에 접근할 것이라 생각했기 때문입니다.
saveAll도 save의 loop로 구성
두 메서드로 실험한 여러 글들을 확인해보면 확실히 saveAll이 더 빠릅니다. 그러나 재밌는 것은 saveAll도 save의 loop로 이루어져있다는 것입니다. 그렇다면 두 메서드의 성능 차이가 있지만, 제가 생각했던 원인은 아니라는 것입니다.
Transaction
중요한 것은 @Transactional 어노테이션으로 표현한 트랜잭션이었습니다. 쿼리들이 언제 commit이 되는지에 따라 성능의 차이를 보이기 때문에, 메서드에 @Transaction이 붙어있는 save는 호출될 때마다 트랜잭션이 commit되며, saveAll은 save의 loop가 끝난 후에 commit되게 되어있습니다.
그러나 트랜잭션으로 오랜 시간 lock이 되어있으면 다른 트랜잭션을 수행할 수 없어 전체적인 성능이 감소할 수 있습니다. 이에 적절히 튜닝하는 방법을 아래 블로그에서 알 수 있었습니다. 대용량 데이터를 저장할 경우 중간중간 트랜잭션을 commit하는 방식입니다.
https://2dongdong.tistory.com/29
https://sas-study.tistory.com/388
https://www.baeldung.com/spring-data-save-saveall
https://stackoverflow.com/questions/49869277/spring-data-save-vs-saveall-performance
'프레임워크 > Spring' 카테고리의 다른 글
[Spring] 예외 처리시 Throws vs try-cat-finally (0) | 2022.01.18 |
---|---|
[Spring] CrudRepository에서 update (0) | 2022.01.16 |
[Spring] 사용하는 객체를 Table로 자동 생성 (0) | 2022.01.10 |
[Spring] CrudRepository를 이용한 table join (0) | 2022.01.10 |
[Spring] HTTP request 보내기 (RestTemplate) (0) | 2022.01.06 |