N+1 문제
연관된 엔티티를 조회할 때 SQL문이 실행되는 것을 N+1 문제라고 한다.
즉시 로딩을 사용할 때도 JPQL은 JPQL만 사용해서 SQL을 생성하기에 N+1 문제가 발생할 수 있다.
모두 지연 로딩으로 설정하고 성능 최적화가 꼭 필요한 곳에는 JPQL 페치 조인을 사용하자.
페치 조인 사용
N+1 문제를 해결하는 가장 일반적인 방법은 페치 조인을 사용하는 것이다.
이때 조심해야 할 것은 일대다 조인일 경우 중복된 결과가 나타날 수 있으므로 JPQL의 DISTINCT를 사용해서 중복을 제거하는 것이다.
하이버네이트 @BatchSize
연관된 엔티티를 조회할 때 지정한 size만큼 SQL의 IN 절을 사용해서 조회한다. 만약 조회한 회원이 10명인데 size=5로 지정하면 2번의 SQL만 추가로 실행한다.
즉시 로딩으로 설정하면 조회 시점에 10건의 데이터를 모두 조회해야 하므로 다음 SQL이 두 번 실행된다. 지연 로딩으로 설정하면 지연 로딩된 엔티티를 최초 사용하는 시점에 다음 SQL을 실행해서 5건의 데이터를 미리 로딩해 둔다. 그리고 6번째 데이터를 사용하면 다음 SQL을 추가로 실행한다.
hibernate.default_batch_fetch_size 속성을 사용하면 애플리케이션 전체에 기본으로 @BatchSize를 적용할 수 있다.
@Entity
public class Member {
@BatchSize(size = 5)
@OneToMany(mappedBy = "member", fetch = FetchType.EAGER)
private List<Order> orders = new ArrayList<Order>();
}
하이버네이트 @Fetch(FetchMode.SUBSELECT)
FetchMode를 SUBSELECT로 사용하면 연관된 데이터를 조회할 때 서브 쿼리를 사용해서 N+1 문제를 해결한다.
@Entity
public class Member {
@Fetch(FetchMode.SUBSELECT)
@OneToMany(mappedBy = "member", fetch = FetchType.EAGER)
private List<Order> orders = new ArrayList<Order>();
}
즉시 로딩으로 설정하면 조회 시점에
지연 로딩으로 설정하면 사용하는 시점에 실행
SELECT O FROM ORDERS O
WHERE O.MEMBER_ID IN (
SELECT
M.ID
FROM
MEMBER M
WHERE M.ID > 10
)
728x90
'JVM > JPA' 카테고리의 다른 글
SQL 쿼리 힌트 사용 (0) | 2023.07.04 |
---|---|
읽기 전용 쿼리의 성능 최적화 (0) | 2023.07.04 |
영속성 컨텍스트와 프록시 (0) | 2023.07.03 |
JPA 예외 처리 (0) | 2023.07.03 |
엔티티 그래프 (0) | 2023.07.03 |