← 질문 목록
#17깊이 0

JPA에서 N+1 쿼리는 왜 생기고 무엇으로 막는가?

프레임워크심화인덱스·질의성능

연관을 지연 로딩으로 두고 목록을 순회할 때 생긴다. 목록을 가져오는 질의 하나에 더해, 원소마다 연관을 채우는 질의가 한 번씩 더 나간다.

  1. DB

    주문 목록 조회. 질의 1번

  2. DB

    1번 주문의 회원 조회

  3. DB

    2번 주문의 회원 조회. 원소 수만큼 반복된다

즉시 로딩으로 바꾸는 것은 답이 아니다. 그러면 연관이 필요 없는 조회에서도 매번 조인이 붙는다. N+1이 사라지는 대신 모든 질의가 무거워진다. 문제를 옮긴 것이지 푼 것이 아니다.

해결은 필요한 자리에서만 한 번에 가져오는 것이다. fetch join이나 @EntityGraph로 그 조회에 한해 함께 읽는다. 어디를 함께 읽을지는 화면이 결정하므로, 매핑이 아니라 질의 쪽에 두는 것이 맞다.

주의

fetch join에도 함정이 있다. 컬렉션을 조인하면 행이 곱해져 부모가 중복되고, 그 상태로는 페이징을 데이터베이스에 맡길 수 없다. 하이버네이트는 이때 전부 읽어 메모리에서 자르며 경고를 남긴다. 목록이 크면 그대로 사고다.

그래서 페이징이 함께 필요한 화면에서는 batch size를 쓴다. 연관을 원소마다 한 번씩이 아니라 IN 절로 묶어 몇 번에 나눠 읽는다. 질의 수가 N에서 N/배치로 줄고 페이징은 데이터베이스가 그대로 맡는다.

추천 꼬리질문

0/300

적은 내용은 AI 학습에 쓰일 수 있습니다. 이름이나 연락처는 넣지 말아 주세요.

관련 질문

JPA에서 N+1 쿼리는 왜 생기고 무엇으로 막는가?