Jun's note

[JPA] 페치조인 (fetch join) , n+1문제 본문

Programming/JPA

[JPA] 페치조인 (fetch join) , n+1문제

junning 2022. 1. 24. 00:21
728x90

페치 조인(fetch join)이란 JPQL에서 성능 최적화를 위해 제공하는 기능이어서 SQL의 조인 종류와는 다르다.

먼저 페치 조인에 대해 알아보기전에, JPQL과 SQL에 대해 간단히 정리해본다.

 

<JPQL vs SQL>

- JPQL: 엔티티를 대상으로 검색하는 객체지향쿼리 (어차피 JPQL식으로 코드 짜서 나중에 SQL로 자동 변환됨)

장점 -> 특정 데이터베이스 SQL에 의존 X

- SQL: 테이블을 대상으로

 

- QueryDSL사용시 주의사항: 수동 flush해주기 (왜? 영속성 디비에 저장된것을 커밋을 통해 실제 디비에 옮겨주는데, 커밋이 뒤에 나오니깐 결과가 0이어서 제대로 결과값이 나오지 않음-> 그러니 em.flush() 수동으로 해주기)

- 동적쿼리!!! , 자바 코드로 쿼리를 짜기때문에 SQL로 오류난 것을 잡을수 있음-> QueryDSL

- JPQL, QueryDSL 만 사용 95%해결 (그럼에도 해결안되는것은 SpringJdbcTemplate 사용


1. 페치조인 (fetch join)

연관된 엔티티를 함께 조회함. 그래서 한번의 쿼리를 날려 한번에 다 조회한다.

  • 목적 : jpql의 성능 최적화 (sql에는 없는 것임)
  • 페치조인은 즉시로딩을 해결할 수 있다. (왜? 여러 엔티티를 한꺼번에 조인해서 하나의 sql문으로 조회하기 때문)
  • 페치조인은 n+1문제를 해결
    • n+1문제란?
    • 운이 안좋을 경우, 서로 다른 값을 조회할때 1차캐시에 저장되는데 모두 다 다른값을 조회할 경우에는 n번 쿼리를 수행해야하기 때문에 성능이 안좋아질수 있음( 이를 페치조인은 한번에 연관된 모든 값을 다 조회함)
  • 일반 조인은 연관된 엔티티를 함께 조회하지 않음

 

2. 페치조인의 한계 (주의사항)

  • 페치조인 대상에는 별칭을 줄 수 없음
  • 페이징 API(setFirstResult,setMaxResults) 사용 x (왜? 일대다 관계에서는 1개이상의 결과가 만들어지게 되어 몇개를 추출할것인지 단정지을 수 x) -> 대신, @BatchSize(size=100)를 사용
  • @BatchSize(size=100) 이란? 연관된 엔티티를 조회할 때 지정된 size 만큼 SQL의 IN절을 사용해서 조회한다. 쉽게말하면 즉시로딩이지만 기능은 지연로딩이랑 비슷하게 100개만큼 모아서 sql 수행 (이렇게 n+1문제 해결하는거임)    (컬렉션경우임)

 

3. 결론 (정리)

- n+1문제는 페치조인으로 해결하자 (그치만 모든 것을 페치조인으로 해결할 수는 없음)

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

 

 

 

Comments