[Spring] JPA save(), saveAll(), deleteAll(), deleteAllInBatch(), @Query 비교

2024. 11. 10. 21:08·SPRING

01. 들어가기전

프로젝트를 하면서, 엔티티의 갯수가 많아지고, 여러 부분을 저장하거나 삭제하는 로직을 구현하는데!

이때 여러 jpa 쿼리메소드가 성능차이가 나는건 알고있었지만, 이유를 정확하게 몰랐다! 까보면서 알아보쟈 !

02.save()

03.saveAll()

  • 둘다 @Transactional 적용되어있음
  • save(): 1건 마다 save()함수 호출
  • saveAll(): 1건 마다 인스턴스 내부의 save()함수 호출

→ saveAll()이 성능이 더 좋은데, 이유가 뭐냐?

  • @Transactional
    • AOP 프록시 기반으로 외부 Bean 객체가 있고, 이 객체의 함수를 호출해 Intercept가 되어 트랜잭션으로 묶이게 됨
    • Bean 객체 내부에서 내부함수 호출 시 @Transcational 적용X
  • save() 호출 시,
    • 상위 @Transactional 존재하는 경우, 해당 Transcation에 참여
    • 존재하지 않은 경우, 새로 Trascation을 생성 후 save 후 commit
    • 외부 빈(repository) 객체의 save 함수 호출
      • 갯수가 많아질수록 비용발생 + 시간 오래걸림
  • saveAll() 호출 시,
    • Bean 객체의 내부함수를 호출하기 때문에 save() 호출마다 Transaction이 생성되거나 참여하는 프록시 로직을 타지않고, 단순 메서드 호출
      • 비용 발생 안함

→ 결론?

출처: https://velog.io/@msung99

  • save(): 300개 데이터 insert시, 트랜잭션 300번 발동
  • saveAll(): 300개의 묶음 단위 하나의 트랜잭션 발동

04.deleteAll()

  • deleteAll() 까보면 while문으로 delete쿼리가 나가기 때문에 사실 delete 쿼리가 하나씩 나감!
  • 결국 데이터가 1000개면 1000번, 10000개면 10000번 돈다는 것이다

05. deleteAllInBatch()

  • "QueryUtils.getQueryString("delete from %s x" 부분이 있는데,
    • 즉, delete from {테이블 이름} 으로 delete 쿼리만 수행!
    • findAll이나 findById를 사용하지 않았기 때문에 delete이전에 select하는 과정은 없음
    • 벌크 작업으로 처리
  • 대용량일 수록 성능 좋음
  • 벌크(Bulk): 한 번의 쿼리로 다수의 데이터를 처리하는 방식
  • 배치(Batch): 데이터를 여러 번에 나누어 처리하는 방식
  • 벌크: 배치처리보다 빠르고 인덱스 활용할 수 있는 장점
    • 전이 메커니즘(cascadeType.ALL)이나 자동 애플리케이션 수준 낙관적 잠금 메커니즘(@Version)의 장점X
    • 엔티티 수정 사항이 영속성 컨텍스트에 자동으로 반영되지 않음
      • 예시)@Version 필드 가진 엔티티에서 삭제 진행시, 엔티티 버전 정보가 업데이트 되지 않음
      • 다른 트랜잭션에서 이 엔티티 참조하고 있을 시, 낙관적 잠금 충돌 감지 못함

07. @Query 사용하기

  • 이때 사실 deleteAllInBatch에서 applyAndBind를 까보면 !! or 연산이 들어가고있었다!

  • 그렇다면 or 대신 in 절을 사용하려면 어떻게 해야하는지! -> @Query를 직접 사용하면된다!
@Modifying
@Query("delete from CommentCard cc WHERE cc.writer.pk = :memberPk")
void deleteCommentCardByMemberPk(@Param("memberPk") Long memberPk);
  • 직접 쿼리를 작성하면 or대신 in 절을 사용하여 한번에 날릴수 있음
  • in절을 사용하면 or을 연속해서 사용하는 것 보다 속도가 훨씬 빠르다!
    • or절: ALL, in절: range를 거침.

 

 

<참고>

https://haon.blog/haon/jpa/bulk-insert/

https://maivve.tistory.com/342

https://haon.blog/haon/jpa/bulk-insert/

https://00h0.tistory.com/97

https://velog.io/@msung99

'SPRING' 카테고리의 다른 글

Redis-MySQL 정합성 보장: 고민, 측정, 그리고 선택  (0) 2026.01.04
[Spring] gradle로 멀티모듈설계 해보기  (3) 2024.11.05
'SPRING' 카테고리의 다른 글
  • Redis-MySQL 정합성 보장: 고민, 측정, 그리고 선택
  • [Spring] gradle로 멀티모듈설계 해보기
jiixon
jiixon
  • jiixon
    Dev:elop
    jiixon
  • 전체
    오늘
    어제
    • 분류 전체보기 (26)
      • JAVA (0)
      • SPRING (3)
      • SERVER (2)
      • 공부 (20)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • POST
    • SETTING
  • 공지사항

  • 인기 글

  • 태그

    자바
    AWS
    Kotlin
    springboot
    junit
    tdd
    알고리즘
    AssertJ
    spring jpa
    배포
    java
    Elastic Beanstalk
    프로그래머스
    테스트
    spring
    Bdd
    서버
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
jiixon
[Spring] JPA save(), saveAll(), deleteAll(), deleteAllInBatch(), @Query 비교
상단으로

티스토리툴바