JPA N+1

N+1 문제는 1개의 쿼리로 N개의 데이터를 조회했을 때, 연관된 데이터를 가져오기 위해 N번의 추가 쿼리가 실행되는 문제입니다.

N+1이 발생하는 과정:

첫 번째 쿼리(1번): 사용자 10명을 조회 sqlSELECT * FROM users LIMIT 10

추가 쿼리(N번 = 10번): 각 사용자마다 주문목록을 개별 조회 sqlSELECT * FROM orders WHERE user_id = 1 SELECT * FROM orders WHERE user_id = 2 … SELECT * FROM orders WHERE user_id = 10

결과: 총 11번의 쿼리 실행 (1 + 10 = 11)

해결 방법

  • 즉시 로딩(Eager Loading): JOIN or FETCH JOIN ``` – N+1 발생 (11번 쿼리) SELECT * FROM users; SELECT * FROM orders WHERE user_id = 1; SELECT * FROM orders WHERE user_id = 2; …

– 즉시 로딩 (1번 쿼리) SELECT u., o. FROM users u LEFT JOIN orders o ON u.id = o.user_id;


- 지연 로딩(Lazy Loading): 배치 사이즈 설정

– 배치 사이즈 5로 설정시 (3번 쿼리) SELECT * FROM users; SELECT * FROM orders WHERE user_id IN (1,2,3,4,5); SELECT * FROM orders WHERE user_id IN (6,7,8,9,10); ```

해결방법은 Fetch join으로 한 번에 조회하거나, @EntityGraph 사용, 배치 사이즈 설정, DTO 직접 조회 등이 있습니다.

실제로 Fetch join을 사용해 300명의 국회의원의 각각의 법안 수를 조회할때 301번의 쿼리를 1번으로 줄여 응답시간을 단축 시킨 경험이 있습니다.