새소식

JPA

N+1 문제 해결 후기

  • -
 

두 엔티티 간에 영속성 전이가 제대로 이루어지려면?

현재 진행하고 있는 개인 프로젝트에서 다음과 같이 엔티티들의 연관관계가 설정되어 있다. Member -- (OneToMany) -- History -- (OneToMany) -- Question 그리고 저장 및 테스트를 용이하게 하기 위해 Member에

dockerel.tistory.com

 

N+1 문제 해결 후기는 위 글과 이어집니다.

 

엔티티 영속성 전이 문제를 어찌어찌 해결한 후 한시름 놨다고 생각할 때쯤 쿼리 로그를 보니 뭔가 이상했다.

 

위 글(영속성 전이 해결 글)에서는 편의상 해결한 후의 쿼리 사진을 사용하였다.

 

무수한 SELECT 요청이 날아가고 있었고, 딱 보자마자 N+1 문제라는 느낌이 확 왔다.

 

그런데 사실 그도 그럴 것이 기존에 멤버가 질문한 개수를 구하는 로직은 이렇게 작성되어 있었다.

 

 

멤버의 history를 구하고 해당 history의 question을 다 구해와서 size를 별도로 구하기 때문에 history에 포함된 question을 다 구하기 위해 쿼리가 history당 1개씩 즉 해당 테스트에서는 100번이나 나간 것이었다.

 

그래서 결국 JPQL을 사용하여 join을 사용한 COUNT 쿼리를 직접 작성하였다.

 

 

이렇게 바꾼 후 쿼리는

 

깔끔하게 한줄로 변했고, 시간은...

 

사실 시간은 별로 안 변했다. 1074ms에서 964ms 정도로 살짝 줄긴 했는데, 나가는 쿼리의 숫자가 줄어들었는 게 더 의미가 있다고 생각한다! 그만큼 디비에 부하가 줄어들겠지...

 

JPA를 책으로만 공부하다가 이번에 프로젝트에서 만나보니까 정말 대규모 트래픽을 가진 서비스에서 N+1 문제가 발생하면 정말 치명적일 것 같다고 느꼈다. 이런 엔티티에 대해 Lazy 하게 혹은 Eager 하게, 영속성 전이를 어떻게 처리할지 그리고 이러한 설정으로 인해 쿼리가 어떻게 나갈지 등에 대해 깊게 고민하며 설계하는 것이 중요할 것 같다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.