N+1 Problem
- N+1 문제란?
ORM의 연관 관계에서 발생하는 문제로,
연관 관계가 설정된 Entitiy를 조회할 경우,
조회된 데이터 갯수 (N) 만큼 연관 관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오는 것을 말합니다.
총 N+1 DB 조회를 하는 문제입니다.
- N+1 예시
사용자와 상품의 관계는, 사용자가 여러개의 상품을 가질 수 있으므로,
User : Product = 1 : N 의 관계를 가집니다.
특정 User를 조회했을 때 , 해당 유저와 관련된 상품을 N번 더 조회합니다.
=> User (SELECT 1번) + 관련 상품 (SELECT N번) = (SELECT N+1번)
- Eager Loading : 즉시 로딩
로딩 시 참조해야 할 데이터들을 미리 전부 가져옵니다.
장점 : 연관된 모든 리소스를 한 번에 가져올 수 있습니다.
단점 : 리소스를 전부 사용하지 않으면 낭비될 수 있고, 초기 로딩 속도가 느려질 수 있습니다.
- Lazy Loading : 지연 로딩
필요한 순간에만 데이터를 가져옵니다.
장점 : Eager Loading에 비해 초기 로딩 시간을 줄일 수 있고, 자원 소비를 줄일 수 있습니다.
단점 : 추가적인 조회 쿼리가 발생합니다.
Spring의 JPA
- 1:N 의 default fetch Type은 Lazy loading
- N:1 의 default fetch Type은 Eager laiding
→ N+1 문제를 겪을 수 있습니다.
N+1 해결 방법
- Fetch Join : JPQL을 사용하여 DB에서 데이터를 가져올 때, 처음부터 연관된 데이터를 같이 가져옵니다. (Join)
- EntityGraph Annotation
- Barch Size : size에 따라 나눠서 조회하는 것으로, N+1 문제가 일어나긴 합니다.
TypeORM
: 어떤 종류의 관계에서도 기본적으로 fetch type을 적용하지 않습니다. 즉, 명시하지 않으면 Eager, Lazy가 아닙니다.
N+1 문제를 해결하는 방법
find
메서드에relation
옵션 적용QueryBuilder
를 사용