정의
1 : N 연관 관계에서 발생하는 문제로, 1 쪽의 엔티티에서 N을 조회할 경우 조회된 데이터 갯수(N)만큼 조회 쿼리가 발생하여 데이터를 읽어오는 문제
목적 및 특징
특징
원인
JPA가 JPQL을 분석해서 SQL을 생성할 때는 Global Fetch 전략을 참고하지 않고 오직 JPQL 자체만을 사용한다.(JPQL 쿼리 자체에 충실하게 SQL을 만든다.)
- findAll()을 한 순간 select t from Team t 이라는 JPQL 구문이 생성되고 해당 구문을 분석한 select * from team 이라는 SQL이 생성되어 실행된다.
- 영속성 컨텍스트에 없다면 2에서 만들어진 team 개수에 맞게 select * from user where team_id = ? 이라는 SQL 구문이 생성된다.
극복 방법
@BatchSize
- 지정된 size만큼 IN절을 사용해서 조회
- 정확히는 N+1 문제를 안 일어나게 하는 방법이 아니라
N+1 문제가 발생하더라도 select * from user where team_id = ? 이 아닌 select * from user where team_id in (?, ?, ?) 방식으로 IN절을 사용해 N+1 문제가 발생하게 하는 방법이다.
이렇게 하면 100번 일어날 N+1 문제를 1+ 1번 조회하는 방식으로 성능을 최적화할 수 있다.
- N의 개수가 많지 않은 경우 사용(size 1000 이하)
- join Fetch
비교군과의 차이
질문
- N + 1 문제가 무엇인가요?
- N + 1 문제의 원인이 무엇인가요?
- N + 1 문제의 극복 방법은 무엇이 있을까요?
출처