Working/jpa 성능 최적화

컬렉션 조회 최적화(oneToMany)

개구리는 개꿀개꿀 2021. 3. 2. 19:01

- v1 : Entity 직접 노출

Order -> List<OrderItem> -> item별 name (lazy loading 초기화)

- v2 : DTO로 변환 리턴

DTO 안에 Entity가 Wrapping 되어있다. OrderItem 도 DTO로 바꿔야 됨

결과 List 안에 또 List가 있으면 N^2으로 쿼리가 늘어남

컬렉션 경우에도 Fetch Join으로 최적화 가능

 

- v3 : Fetch Join

 원하지 않게 join이 많이 됨

distinct o 추가로 사용하면 유니크하게 나옴

sql 쿼리는 1번만 요청한다.

단점 - 페이징 불가능

 

 

- v3.1 : 컬렉션을 페치조인 하면 페이징 불가

1:N 조인 -> 데이터가 N개가 된다, 데이터는 N을 기준으로 페이징이 됨 -> 1을 기준으로 하고싶다.

1. xToOne(OneToOne, ManyToOne) 관계를 모두 fetch join 한다(row수 증가 X)

2. 컬렉션은 지연 로딩

3. hibernate.default_batch_fetch_size, @BatchSize를 적용한다

-> sql문에서 in절을 사용해서 한번에 가져온다

-> 쿼리 호출 수가 1+N -> 1+1 로 최적화 된다.

xToOne 관계는 fetch join해도 페이징에 영향을 주지 않기때문에 사용해서 쿼리 수를 줄이고 hibernate.default_batch_fetch_size 사용!

100~1000(in절 size limit 1000), 500정도가 안전? 1000이하에서 순간 부하를 견딜수 있을 만큼

 

- v4 : 컬렉션 DTO

받을수 있는 부분만 받고 컬렉션은 바로 받을수 없기 때문에 결과를 한번 더 돌면서 조회

N + N 문제 발생

 

- v5: 두번째 컬렉션을 조회할 때 in절을 사용해서 N->1로 한번에 가져오게 바꾼다.

toOne 관계들을 먼저 조회하고, 여기서 얻은 id로 toMany관계를 in절을 사용해서 한번에 조회하자

Collectors.groupingBy로 받아서 채워주자