CS 잡지식

[1:다]에서의 컬렉션(다) 조회 시 문제 : 페이징, (N+1)문제 (매우 매우 중요)

JIN_YOUNG _KIM 2023. 5. 5. 18:23

https://jbluke.tistory.com/426 ( 이 사이트의 맥락에 이어서 설명을 하겠다)

 

컬렉션(Collection) fetch join 시, 발생하는 [데이터 중복] 문제!(소위 [데이터 뻥튀기]라고도 부름)

[1:다]에서 생기는 문제이기도 함. (아래 사이트 참조) (하이버네이터 6부터는 자동으로 데이터 중복 해결해줌. (Feat. distinct) https://jbluke.tistory.com/346 1:多 jbluke.tistory.com @Entity @Table(name = "ORDERS") @Ge

jbluke.tistory.com

 

그럼, [1:다] 관계에서 발생하는,즉 컬렉션(다) 조회 시 발생하는 [페이징] 이슈를 해결할 방법은 없는건가???

(참고로, [1:다]에서 생기는 이슈는 [다:다]에서도 똑같이 생기는데, [다:다] 관계는 절대 사용하면 안된다. 고로, 

컬렉션 문제는 [1:다]로 한정하고 생각해도 평생 문제 없음)

해결 방법은 아래 방법 밖에 없다. (ppt 26)

1] 먼저 ToOne(Member,Delivery) 관계를 모두 페치조인 한다(Order입장에서 ToOne 관계는 Member, Delivery)

-> ToOne 관계는 row수를 증가시키지 않으므로 페이징 쿼리에 영향을 주지 않는다.

-> @~ToOne 관계는 fetch join으로 (1+N) 문제를 해결하겠다는 뜻이다.

(@~ToOne 관계는 애초에 [페이지] 이슈가 생기지 않으므로, 1]에서는 [페이지]에 대한 내용은 없다) 

 

2] 컬렉션(OrderItem)은 지연 로딩(Lazy)으로 [조회]한다( [ 1 : 다] 관계에서의 [다] 쪽을 Lazy 조회 ) 

-> 즉 [1:다] 관계에서 다(컬렉션)은 fetch join으로 조회x.

Lazy를 걸어서, 직접 호출하는 방식으로 조회를 하나????????

Nope!!! Lazy를 때문에 생기는 (N+1) 문제는 Fetch Join이 아니더라고 유일하게 아래의 방법으로

최적화가 가능하다. 

 

3] 지연 로딩 성능 최적화를 위해 hibernate.default_batch_fetch_size , @BatchSize 를 적용한다.

->hibernate.default_batch_fetch_size : 글로벌 설정

@BatchSize: 개별 최적화

이 옵션을 사용하면 컬렉션이나, 프록시 객체(ITEM)를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회한다.

-> 1] -> 2] ->3]  순으로 [1:다] 관계에 있어서의 컬렉션(OrderItem) 조회 이슈를 해결한다. 

( 1] : 이 과정에서 제일 먼저, Member, Delivery가 fetch join되어 조회된다[여기서 페이징이 일어남. 절대 컬렉션인       OrderItem을 조회할 때 일어나면 안됨. 그런면 페이징 이슈 해결이 안됨.]

   2]-1 : 이 과정에서 OrderItem(컬렉션)이 설정된 fetch_size만큼 조회된다.

   2]-2 : OrderItem이 조회되면 이제 Proxy 객체인 ITEM에 대해서도 fetch_size만큼 조회된다.

정확한 것은 게시물 428을 참고하면 된다.