JPA N+1문제

Bong2·2022년 4월 23일

Spring

목록 보기
5/9

JPA N+1 문제란?

JPA의 Entity 조회시 Query한번 내부에 존재하는 다른 연관관계에 접근할 때 또 다시 한번 쿼리가 발생하는 비효율적인 상황

조회시 바로 DB에 SQL쿼리를 날리는 것이 아니라 JPQL이라는 객체지향 쿼리 언어를 생성, 실행시킨 후 JPA는 이것을 분석해서 SQL을 생성, 실행하는 과정에서 N+1이 발생

JPQL은 LAZY로딩, EAGER 로딩과 같은 글로벌 패치전략을 신경쓰지 않고 JPQL만 사용해서 SQL을 생성

JQPL
플랫폼에 독립적인 객체지향 쿼리 언어
자바 코드에서 데이터베이스를 조회할 때 특정 SQL이나 저장 엔진에 종속되지 않게 도와줌

언제 발생?

1:N 또는 N:1 관계를 가진 엔티티를 조회할 때 발생

  • JPA Fetch 전략 EAGER 전략으로 데이터를 조회하는 경우
  • JPA Fetch 전략 LAZY 전략으로, 전체 데이터를 가져온 이후 연관 관계인 하위 엔티티를 사용할 때 다시 조회하는 경우

N+1 문제 해결 방법

1. Fetch Join

패치 조인이란, JPQL에서 성능 개선 및 최적화를 위해 제공하는 기능으로 연관된 엔티티나 컬렉션을 함께 한번에 조회하는 역할을 합니다. 이는 SQL 쿼리를 통해 객체 그래프를 한번에 조회할 수 있습니다.

미리 쿼리로 테이블을 조인해서 가져오기 때문에 LAZY, EAGER 두 개의 전얄게 해당되는 해결법
@Query 활용해 SQL문 안에 join fetch를 사용
ex)

@Query("select DISTINCT a from Album a join fetch a.songs")
List<Album> findAllJoinFetch();

단점

  1. JPA가 제공하는 Pagable 기능 사용 불가(페이징 API)
  2. 1 : N 관계가 2개인 엔티티를 패치 조인 사용불가

    임시 해결법 List -> Set으로 자료구조변경
    JPQL에 distinct 추가 설정

  3. 번거롭게 쿼리문을 작성해야 함

2. Batch Size 조절

설정한 size만큼 데이터를 미리 로딩.
JPA의 페이징 API 기능처럼 개수가 고정된 데이터를 가져올 때 함께 사용할 때 유용하게 사용 가능할 듯합니다.
@BatchSize(size = 5)
EAGER 설정으로 바꿔서 사용해야된다.

profile
자바 백엔드 개발자로 성장하자

0개의 댓글