JPA #8 - 컬렉션 조회 최적화 2

업데이트:

JPA 학습

API 개발 고급 - 컬렉션 조회 최적화

주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파

  • 1:N에서 컬렉션을 페치 조인하면 DB에서 N만큼 row가 증가한다. 우리가 원하는 것은 1에 대해 페이징을 해야하는데 N만큼 증가해서 문제가 발생한다.
  • 솔루션
    • XToOne 관계의 경우 모두 fetch join 한다. row가 증가하지 않으므로 페이징에 문제가 없다.
    • 컬렉션은 지연 로딩으로 조회하고 성능 최적화를 위해 hibernate.fefault_batch_fetch_size, @BatchSzie 적용한다.
      • hibernate.default_batch_fetch_size : 글로벌 설정
      • @BatchSize : 개별 최적화
      • 여기서 사이즈는 한번에 조회 할 인쿼리 갯수를 의미한다. 무조건 크다고 좋은 것이 아니고 적절하게 선택해야 시간과 부하를 적당히 조절 할 수 있다. (예 : 100개 10번 요청 시 시간증가 vs. 1000개 1번 요청 시 WAS DB부하가 증가)
      • 이 옵션을 사용하면 컬렉션이나, 프록시 객체를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회한다.
  • 정리
    • V3 쿼리는 한번에 모든 데이터를 요청하지만 DB 에서 중복데이터가 많이 생성되고, 그 데이터를 전부 어플리케이션 단으로 전송한다. (데이터 양이 많을 경우 용량이 많아고 단점이 있다.)
    • V3.1 쿼리1:N:M의 쿼리를 인쿼리를 이용하여 1:1:1로 만들어 준다. 쿼리수는 V3에 비해 증가했지만, DB단에서 데이터가 중복없이 최적화되어서 날아온다.
    • 두 방식은 네트워크를 호출하는 비용과 전송하는 비용에서의 트레이드 오프가 있으니 적절히 잘 사용하도록 한다. 그러나 V3.1 방식을 권장한다.
    • 데이터는 DB단에서 페이징해서 오는 것이 맞고 어플리케이션 단에서 for문으로 잘라 사용하는 것은 옳지 않다.
  • 장점
    • 쿼리호출수가1+N 1+1로최적화된다.
    • 조인보다 DB 데이터 전송량이 최적화 된다. (Order와 OrderItem을 조인하면 Order가 OrderItem 만큼 중복해서 조회된다. 이 방법은 각각 조회하므로 전송해야할 중복 데이터가 없다.)
    • 페치 조인 방식과 비교해서 쿼리 호출 수가 약간 증가하지만, DB 데이터 전송량이 감소한다.
    • 컬렉션 페치 조인은 페이징이 불가능 하지만 이 방법은 페이징이 가능하다.
  • 결론
    • ToOne 관계는 페치 조인해도 페이징에 영향을 주지 않는다. 따라서 ToOne 관계는 페치조인으로 쿼 리 수를 줄이고 해결하고, 나머지는 hibernate.default_batch_fetch_size 로 최적화 하자.

댓글남기기