Jpa N+1 문제

ysh·2023년 11월 2일
0

인턴십

목록 보기
16/25

: 연관 관계(@ManyToOne 등) 설정된 엔티티를 사용할 때 발생할 수 있는 문제.

: 특정 엔티티에서 findAll()을 했을 때,

: FetchType을 EAGER로 설정했을 시에는 findAll()을 실행하고 해당 엔티티에 연관되어 있는 엔티티를 findAll()의 size(데이터의 개수)만큼, 즉 조회된 행 하나마다 해당 연관 엔티티를 조회하는 select문을 날리게 된다. (n+1 문제 발생)

: LAZY로 설정 시에 findAll()을 실행할 때에는 연관 엔티티가 조회(select)되지 않지만, 해당 연관 엔티티의 데이터가 사용될 시에는 select문으로 엔티티를 조회하기 때문에 결국 데이터n개 + 1개 만큼의 쿼리가 나가게 된다. (n+1 문제 발생)

해결법

Fetch Join

: JPQL을 사용하여 처음부터 연관 데이터까지 가져오도록. (SQL의 Join문)
: 우리가 원하는 데이터를 최적화하여 가져올 수 있게.
: InnerJoin (교집합)

단점

: 페이징을 사용할 수 없다.
: LAZY로 FetchType을 설정하여 놓더라도, JPQL로 직접 해당 데이터들을 join하기 때문에 LAZY설정이 소용이 없다.

@EntityGraph

: JPQL을 사용하고, 어노테이션을 이용하여 쿼리 수행 시에 가져올 필드 명을 적어 Join하는 방법.
: FecthJoin과는 다르게 OuterJoin이 실행됨.(합집합)

단점

: FecthJoin과 함께 EntityGraph는 중복 데이터가 발생한다.(카테시안 곱이 발생한다고 한다.)
-> distinct를 이용하여 중복 데이터를 없앨 수 있다.

@Fetch(FetchMode.SUBSELECT)

: 쿼리로 엔티티를 조회할 때 서브 쿼리로 이 어노테이션이 적용된 연관 엔티티를 불러오는 방식.

@BatchSize(size = ?)

: 연관된 엔티티를 조회 시 현재 엔티티의 ID를 설정한 Size만큼 ID를 모아, IN절에 담아 조회하는 방식.
: EAGER 설정 시엔 조회 시 IN절, LAZY는 size만큼의 연관 엔티티가 사용되고, 더 필요할 시에 size만큼 추가 로딩.

QueryBuilder

: Query를 직접 최적화 하여 사용 가능.
: 코드로 쿼리문을 작성하는 느낌.

profile
유승한

0개의 댓글

관련 채용 정보