Fetch Join을 사용하자..!

MinSeong Kang·2022년 9월 23일
0

나만의 노트

목록 보기
2/2

해당 포스팅은 김영한님의 Fetch Join 관련 강의를 들으면서 위키를 작성하듯이 작성한 글입니다~~ 가볍게 봐주시길 바랍니다.

  • JPQL에서 성능 최적화를 위해 제공하는 기능
  • 연관된 엔티티나 컬렉션을 SQL 한번에 함께 조회하는 기능!!
  • join fetch는 Inner Join과 같은 역할을 한다.

ex)

select m from Member m join fetch m.team = 

select M.*, T.* From Member M INNER JOIN TEAM T ON M.TEAM_ID = T.ID

문제

즉시로딩을 하든, 지연로딩을 하든 N+1 문제는 무조건 발생!!

  • 팀과 멤버 관계에서 멤버 조회시 팀의 이름도 알고 싶을 때
  • 멤버조회 (1) + 각 멤버들의 팀 조회(N) -> N+1 문제
  • 최악의 경우 N+1, 팀이 공통되는 경우, 영속성 컨텍스트가 1차 캐시 역할을 한다.
  • fetch join - 프록시 객체가 담기지 않음!! 실제 엔티티가 영속성 컨텍스트에 올라와 잇음!!!
  • 지연로딩보다 fetch join이 우선시!!

주의점

컬렉션 페치조인? - 일대다 관계, 컬렉션 페치 조인

  • 디비입장에서 일대다 조회시 데이터가 뻥튀기 되어 조회된다.

memberA - teamA
memberB - teamA
memberC - teamB

select t from Team t join fetch t.members

다음과 같이 조회 - ID(PK)가 동일한 튜플이 조회된다.!!

  • SQL의 DISTINCT를 통해 중복 제거 - 튜플의 값이 완전히 똑같아야 중복 제거가 됨.
  • JPQL의 DISTINCT 2가지 기능 - SQL에 DISTINCT 추가, 애플리케이션에서 중복 엔티티 제거 - 같은 식별자를 가진 Team 엔티티를 제거

select distinct t from Team t join fetch t.members

페치 조인 vs 일반 조인

  • select t from Team t join fetch t.members

실제 join되는 데이터는 가져오지 않는다. N+1 문제 발생!!
연관된 엔티티를 함께 조회하지 않음! Select 절에 지정한 엔티티만 조회

  • select t from Team t join t.members

객체 그래프를 SQL 한방에 조회


페치 조인의 한계

  • 페치조인 대상에는 별칭을 줄 수 없음!! where문을 쓰면 위험함.
  • 연관관계 엔티티에 대한 조건을 줘서 거르면서 조회하면 안됨..!! 원래 데이터가 5개인데 데이터가 3개밖에 안나옴. JPA는 페치 조인시 전체를 다 가져와야함.
  • 객체 그래프는 거르면서 데이터를 조회하면 좋지않음..! 데이터의 정합성과 JPA 사상과 맞지 않음!
  • 둘 이상의 컬렉션은 페치 조인을 할 수 없음! 일대다대다 ~~~ -> 데이터 정합성이 안맞음, 데이터가 뻥치기 되어 데이터 갯수가 곱의 곱이 될 수 있다.
  • 컬렉션을 페치 조인하면 페이징 API(setFirstResult, setMaxResults)를 사용할 수 없음. -> 데이터 뻥튀기를 페이징을 한다 ?? 안된다. 일대다 페치 조인 데이터 뻥튀기 팀에 속한 멤버가 잘린다.!! -> 페이징 처리가 안되고 모든 데이터를 가져옴!!
    -> 뒤집어서 다대일로 조회하여 페이징 방향을 변경

-> @BatchSize(size=1000)
-> global 세팅 hibernate.default_batch_fetch_size value=1000 -> 1000이하의 적절한 수

-> 쿼리가 N+1이 아닌 테이블 수에 맞출수 있음??

  • 연관된 엔티티들을 SQL로 한번에 조회 - 성능 최적화

  • Fetch Join은 엔티티에 직접 적용하는 로딩 전략보다 우선권을 가짐.

  • 모든 로딩전략은 모두 지연 로딩

  • 최적화가 필요한 곳은 페치 조인 적용 !!

  • 모든 것을 페치 조인으로 해결할 수 없음

  • 페치 조인은 객체 그래프를 유지할 때 사용하면 효과적

  • 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야 하면, 페치 조인 보다는 일반 조인을 사용하고 필요한 데이터들만 조회해서 DTO로 반환하는 것이 효과적

  • 엔티티 조회 (fetch join) 그대로 사용

  • fetch join해서 애플리케이션에서 dto로 변환해서 사용

  • 뉴 오퍼레이션에서 DTO로 스위칭해서 가져온다

0개의 댓글