//
Search
🕥

N+1

조회 시 1개의 쿼리가 날라갈것으로 생각했지만 나오지 않아도 되는 조회의 쿼리가 N개가 더 발생하는 문제
N+1 문제는 fetch 전략이 Eager이든 Lazy이든 상관없이 발생한다.
Eager: 먼저 대상 테이블 조회 쿼리가 나가고 전략이 eager인것을 확인 후 연관관계에 있는 테이블 조회가 N개가 나간다.
Lazy: 대상 테이블 조회 쿼리가 나가고 추후 연관관계에 있는 객체의 데이터를 사용하고자 할때 관련 조회 쿼리가 N개가 다시 나간다.

Fetch join

위의 문제를 해결하고자 fetch join을 사용한다.
fetch join을 사용하여 연관관계에 있는 값도 한방쿼리로 가져올 수 있다.
@EntityGraph
*주의 사항: OneToMany 패치 조인에서 distinct을 걸지 않으면, 값이 중복되어 가져와진다.

Fetch join이 만능이 아닌이유

1.
ToMany 관계에서 Collection이 2개 이상이 있을 경우 MultipleBagFetchException이 발생한다.
fetch join을 복수의 컬렉션에 적용하게 되면 카테시안 곱에 의해 중복 데이터가 발생하기 때문이다
→ Set 사용 or batch size 사용
2.
Pagination 사용 불가
fetch join에서 pagination을 사용하면 모든 데이터를 select해서 인메모리에 저장하는 형식이다
이렇게 진행될 시 페이징처리를 하려는 목적과 맞지 않는다.

Batch Size

N+1을 해결 방법으로는 batch size를 설정도 있다
@BatchSize로 설정할 수도 있지만 application.properties로 전역으로 설정해주는 방법도 있다.
먼저 대상 테이블을 조회한 다음에 연관관계 있는 테이블 조회 쿼리를 N만큼 날리는게 아닌 batch size만큼 in함수안에 조회할 id 값들을 넣어줘서 날리는 방법이다.
만약 테이블에 데이터가 1000개 있고 batch size를 1000으로 설정해주었다면 총 2번의 쿼리가 발생하겠지만 테이블에 데이터가 얼마나 들어있는지 가늠이 안간다면 batch size를 적절하게 설정해주지 못한다는 단점이 있다.