ORM프레임워크

<JPA> N+1 문제

Mulenga 2023. 2. 27. 07:18
728x90

JPA에서 N+1 문제란, 엔티티를 조회할 때 관계 매핑된 엔티티를 함께 조회할 때 발생하는 성능 문제이다. N+1 문제는 지연 로딩(lazy loading)과 일대다 및 다대다 관계 매핑 시 많이 발생한다.

 

예를 들어, 학교(School)와 학생(Student) 엔티티가 일대다 관계를 가지고 있다고 가정해보자. 즉, 하나의 학교는 여러 명의 학생을 가질 수 있으며, 하나의 학생은 하나의 학교에만 속할 수 있다.

 

이 때, JPA에서 일대다 관계를 조회할 때 N+1 문제가 발생할 수 있다. 예를 들어, 다음과 같은 코드로 학교에 속한 모든 학생의 이름을 출력하려고 할 때,

List<School> schools = schoolRepository.findAll();

for (School school : schools) {
    List<Student> students = school.getStudents();
    for (Student student : students) {
        System.out.println(student.getName());
    }
}
 

이 코드에서는 학교를 조회하는 쿼리가 한 번 실행된다. 그러나 각 학교의 학생들을 조회하기 위해 학생 엔티티에 대한 추가적인 쿼리가 각 학교마다 실행된다. 이 경우, 학교가 N개이고 각 학교에 대해 학생 조회 쿼리가 한 번씩 실행되므로, 전체 쿼리 실행 횟수는 N+1이 된다.

 

N+1문제 해결 방법

 

1. 페치(fetch) 조인 사용

페치 조인(fetch join)은 연관된 엔티티들을 함께 조회하는 방법이다. 기본적으로 JPA는 연관된 엔티티를 지연 로딩(lazy loading)으로 조회하기 때문에 N+1 문제가 발생할 수 있다. 하지만 페치 조인을 사용하면 한 번의 쿼리로 연관된 엔티티를 모두 조회할 수 있으므로 N+1 문제를 해결할 수 있다.

예를 들어, 다음과 같이 JPQL 쿼리를 작성하면 페치 조인을 사용할 수 있다.

 
SELECT s FROM School s JOIN FETCH s.students

2.엔티티 그래프(Entity Graph) 사용

 

엔티티 그래프(Entity Graph)는 JPA 2.1부터 도입된 기능으로, 연관된 엔티티를 한 번에 조회하는 방법이다. 엔티티 그래프를 사용하면 JPA에서 자동으로 페치 조인 쿼리를 생성하여 N+1 문제를 해결할 수 있다.

예를 들어, 다음과 같이 엔티티 그래프를 사용하면 모든 연관된 엔티티를 함께 조회할 수 있다.

@EntityGraph(attributePaths = {"students"})
@Query("SELECT s FROM School s")
List<School> findAllWithStudents();
 
 
 

 

'ORM프레임워크' 카테고리의 다른 글

<JPA> JPA란 무엇인가?  (0) 2023.01.18
<Mybatis> 마이바티스 동적 쿼리 문법(1)  (0) 2022.05.19