DB
FETCH JOIN
KJihun
2025. 3. 18. 15:17
728x90
FETCH JOIN
ORM(Object-Relational Mapping) 프레임워크나 SQL에서 JOIN 된 엔티티를 한 번의 쿼리로 가져오는 기법
- 일반적으로 SQL의 JOIN은 기본적으로 지연 로딩(Lazy Loading) 방식으로 동작한다
- FETCH JOIN을 사용하면 즉시 로딩(Eager Loading) 방식으로 가져와 여러 번의 쿼리를 실행(N+1) 하는 것을 방지할 수 있다
2. FETCH JOIN in SQL (JPA / Hibernate)
📌 일반 JOIN (Lazy Loading)
SELECT e FROM Employee e JOIN e.department d;
- 이 경우, 지연 로딩(Lazy Loading)으로 처리되며, department 데이터는 필요할 때 추가 쿼리가 발생한다
📌 FETCH JOIN (Eager Loading)
SELECT e FROM Employee e JOIN FETCH e.department;
- department 데이터도 즉시 로딩되며, 한 번의 쿼리만 실행되므로 성능이 향상된다
FETCH JOIN의 장점
✅ 즉시 로딩 → 한 번의 쿼리로 연관된 데이터를 가져옴
✅ N+1 문제 해결 → JPA에서 Lazy Loading을 사용할 때 발생하는 N+1 문제를 방지
FETCH JOIN 사용 시 주의할 점
- 한 번에 많은 데이터를 가져오기 때문에, 데이터가 많아지면 메모리 사용량이 증가한다
- DISTINCT를 사용하지 않으면 중복 데이터가 발생할 수 있다
- 페이징 불가능 (JOIN FETCH + LIMIT 조합 불가)
- JPA / Hibernate에서는 FETCH JOIN을 사용할 경우, 페이징 (LIMIT, OFFSET)이 제대로 동작하지 않음
- 이유: FETCH JOIN이 실행되면, 모든 데이터를 먼저 가져온 후 메모리에서 페이징을 수행하기 때문
✅ 예제 (페이징 적용 실패)
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e JOIN FETCH e.department", Employee.class
);
query.setFirstResult(0);
query.setMaxResults(10); // ❌ 동작하지 않음!
- 이 경우, 모든 데이터를 가져온 후 10개만 메모리에서 추려내므로, 쿼리 성능 저하
- 해결 방법
- JOIN FETCH를 제거
- 서브쿼리 방식을 활용
서브쿼리 활용
SELECT e FROM Employee e
WHERE e.id IN (
SELECT e2.id FROM Employee e2 ORDER BY e2.id LIMIT 10
)
JOIN FETCH e.department;
- LIMIT으로 10개 데이터를 추려낸 후 JOIN FETCH를 수행
- Hibernate에서는 기본적으로 지원하지 않으므로, 네이티브 쿼리를 활용하여야 함