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번으로 줄여 응답시간을 단축 시킨 경험이 있습니다.