스프링/JPA

만약 대량의 데이터를 지워야 할 일이 있다면??? (JPA)

지팡구 2023. 1. 14. 16:40

들어가기

만약 우리가 게시물을 지워야 한다면? 게시물과 연관된 테이블의 데이터를 먼저 지운 후 게시글을 지워야 한다.

게시물은 하나만 지우면 끝이지만, 게시물에 작성된 댓글이 만약 무수히 많다면?

 

연관관계 설명

 

게시글 - 사용자 : Many to One (다대일)

게시글 - 댓글 : Many to One (다대일)

 

 

만약 윗 코드처럼 댓글을 지우게 된다면 댓글의 갯수많큼 delete 쿼리가 발생할 것이다. 

댓글이 많이 존재하지 않으면 괜찮은데, 이 댓글이 무수히 많다면? 성능상에 이슈가 발생할 여지가 생길 것이다.

 

어떻게 이를 해결할 수 있을까? 


본론

이 글의 시작은 게시물에서 시작되었다.

 

예를 들어서 1번 게시물을 지우고자 할때, 윗 그림에서 확인할 수있는 것처럼, 연관관계가 맺어져 있기에 연관괸 데이터부터 지워야 한다. 일반적으로 jpa에서 제공하는 쿼리를 사용해도 되지만 deleteByX 계열의 쿼리는 삭제하는 대상들을 전부 조회하고 (쿼리문 1개), 그 삭제 대상들을 1건식 (총 N번)삭제하는 이슈가 있었다.

 

이런 물음에 궁금증을 느끼게 되었고, 해결챚을 찾고자 생각해본바는 다음과 같다.

  • 우선 delete 쿼리가 많이 나가면 성능상의 이슈가 있을까?  - 조회 로직도 아닌데?
  • 어떻게 줄일 수 있을까? (만약에 사용해야한다면 직접 쿼리를 짜야할 것 같은데)... 

이와 같은 생각들을 하게 되었고, 우선 후자의 방식을 선택하기로 했다.

 

일단 우선 Jpa의 delete method를 추적해보면 다음과 같다. 

springframework>data>jpa>repository>query>JpaQueryExecutuin>DeleteExecution>doExecute

여기서 코드를 확인해보면 for 루프에서 해당 object 객체를 하나씩 지우는 것을 확인할 수 있는데, 이로 인해 Jpa는 deleteByX와 같은 쿼리 메소드를 사용하면 삭제하고자 하는 데이터를 조회하고, 그 결과로 얻은 데이터를 1건식 삭제한다.

 

이러한 문제를 해결하기 위해  앞서 설명한 것처럼, 직접 쿼리를 생성했다. 

 

이러한 방식으로 직접 쿼리를 작성하게되면, 해당 쿼리 메소드가 호출될 때, 해당 쿼리가 나가는데,

해당 쿼리를 실행해보면 in query를 이용해 데이터를 한번에 지워주는 것을 확인할 수 있었다. 

 

맨 처음에는 그냥 쿼리문만짜면 되겠지 했는데, 

이러한 오류를 뱉어내었다 

해당 발생한 exception에 관한 정리는 아랫 글에 담았다.

2023.01.14 - [오류발생과 해결] - [Error] QueryExecutionRequestException : Not supported for DML operations

 

이렇게 문제를 해결하고 쿼리문을 확인해보니 여러개가 나가던 query 문이 in query로 인해 하나의 쿼리문으로 줄어듬을 확인할 수 있었다.

 

결과

마무리 ( 참고 )

https://jojoldu.tistory.com/235