티스토리 뷰

스프링JPA를 이용할 때 나타날 수 있는 N+1 문제는 무엇이며 어떻게 해결해야 할까?

  • N+1은 JPA를 이용해서 데이터를 조회할 때 한 개의 쿼리로 처리되길 기대했는데 N개의 추가 쿼리가 발생하는 현상으로 불필요한 리소스를 낭비하고 조회 성능을 악화시키는 문제이다.
  • 예를 들어 멤버와 팀간 관계를 생각해볼 때, 한 명의 멤버는 하나의 팀을 가질 수 있고 팀 입장에서는 여러 명의 멤버를 가질 수 있는데 team1의 멤버를 findAll() 하게 되면 멤버들을 전체 조회하는 쿼리가 먼저 나가고 그 다음으로 멤버수만큼 멤버를 조회하는 쿼리가 추가로 나가게 되는 것이다.
  • N+1문제가 발생하는 이유는 JPA와 JPQL의 동작 특성 때문이다. JPA가 JPQL을 분석해서 SQL을 생성할 때는 글로벌 Fetch전략을 생각하지 않고 오직 JPQL만을 가지고 쿼리를 생성한다. 그래서 team1의 멤버를 findAll() 했을 때 먼저 멤버들을 전체 조회한 쿼리만 나간 것이고, 그 후에 연관되어 있는 user도 조회해야 하는데 이미 팀에 대한 조회가 끝나서 join이 불가능하기 때문에 일일이 select 해서 N개 만큼 추가로 쿼리가 나간다.
  • 이것은 연관된 엔티티나 컬렉션을 한 번에 같이 조회하는, JPQL에서 성능 최적화를 위해 제공하는 기술인 fetch join과 EntityGraph 어노테이션, 그리고 설정한 수 만큼 In절을 사용해 데이터를 한꺼번에 가져오는 @BatchSize를 이용해 사이즈를 조정함으로써 해결할 수 있다.

참고

  • JPQL은 SQL을 추상화한 객체지향 쿼리 언어로써, 자바 코드에서 DB를 조회할 때 특정 SQL 방언이나 DB에 종속되지 않도록 해준다.
  • JPA는 이러한 JPQL을 분석해서 SQL로 변환한 후 DB에서 조회하게 된다.

연관자료

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함