우주먼지
Published 2023. 3. 19. 13:29
JPQL Fetch Join Database/JPQL

1. 💡 Fetch Join

  • SQL 조인의 종류가 아니다.
  • JPQL에서 성능 최적화를 위해 제공하는 기능이다.
  • 연관된 Entity나 Collection을 SQL 한 번에 같이 조회하는 기능 (성능 최적화)
  • 글로벌 Fetch Loading 전략보다 우선순위가 높다.
  • 객체 그래프를 유지할 때 사용하면 효과적이다.
  • 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야하면,
    일반 조인을 사용하고 필요한 데이터만 조회해서 DTO로 반환하는 것이 좋다.
  • join fetch 명령어 사용
  • ::= [ LEFT [OUTER] | INNER ] join fetch 경로

 

1.1. Entity Fetch Join

엔티티를 조회하면서 연관된 엔티티까지 같이 한번의 쿼리로 조회한다.

JPQL

<code />
String query = "select m from Member m join fetch m.team";

SQL

<code />
SELECT M.*, T.* FROM Member M INNER JOIN Team T ON M.team_ID = T.ID

 

1.2. Collection Fetch Join

주로 1:N 관계에서 컬렉션을 가져올 때 사용한다.

중복된 ID값이 있을겅우 distinct를 사용해 컬렉션에서 중복을 제거하지 않으면

보통 원래 데이터보다 더 큰 결과집합이 반환된다.

JPQL

<code />
String query = "select distinct t from Team t join fetch t.members where t.name = 'teamA'";

SQL

<code />
SELECT T.*, M.* FROM Team T INNER JOIN Member M ON T.ID = M.Team_ID WHERE T.name = 'teamA';

 

1.3. 한계

  • fetch join 대상은 왠만하면 Alias 부여를 하지 않는게 좋다. (데이터 정합성의 이유)
  • 둘 이상의 컬렉션은 Fetch Join을 할 수 없다.
  • 컬렉션을 Fetch Join하면 페이징 API를 사용할 수 없다
    • setFirstResult, setMaxResults 등 사용불가능
    • 1:1, N:1 같은 단일 값 연관 필드들은 Fetch Join시 페이징 API를 사용 가능하다.
    • Hibernate는 경고 로그를 남기고 메모리에서 페이징한다. (매우 위험)

 

1.4. 컬렉션 페이징 API 적용

fetch join으로 해결이 불가능한, 컬렉션에 페이징을 적용하려면 BatchSize를 활용한다.

@BatchSize(size = 100), 값은 1000 이하의 적절한 값으로 설정한다.

yml 설정은 hibernate.default_batch_fetch_size의 value도 설정해주면 된다.

이렇게 Batch Size를 설정하면 N+1 쿼리가 아닌 테이블의 수 만큼 쿼리를 맟출 수 있다.

 

1.5. 생각해보기

객체 그래프라는건 기본적으로 연관된 데이터를 전부 가져오는것이다.

 

하지만 fetch join을 하고 조건을 걸어 전체가 아닌 일부만 가져오는것보다,
그냥 직접 그 데이터들을 가져오는 쿼리를 작성하는게 더 낫다.

 

그리고, 단일 값 연관 필드가 아닌 컬렉션 값 연관 필드처럼 여러개의 값을 가진 쿼리의
페이징 API가 안되는 이유를 생각해보자.

 

간단한 예시로 팀이 "A"인 회원 2명을 조회하고 총 2페이지에 페이지당 1건을 출력한다고 가정한다.

 

그럼 2건의 반환 결과 중 한 페이지에 한개의 데이터만 들어가고 다른 하나가 누락되며,
반환결과에 팀 "A"는 회원을 하나만 가지고 있게 되는 셈이다.

'Database > JPQL' 카테고리의 다른 글

JPQL 벌크 연산 & 다형성 쿼리 & Named 쿼리  (0) 2023.03.22
JQPL 경로표현식  (2) 2023.03.19
JPQL Type Query & Sub Query  (0) 2023.03.11
JPQL Paging API & Search Result API  (0) 2023.03.11
JPQL Projection  (0) 2023.03.11
profile

우주먼지

@o귤o

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그