JPA

yshjft·2022년 6월 4일
0

Fetch join + 페이징

스프링 데이터 JPA에서 fetch join이 들어간 경우 Count 쿼리를 정상적으로 만들어내지 못한다. 따라서 페이징을 정상적으로 처리하기 위해서 아래와 같이 countQuery 부분을 별도로 분리해서 처리 해주어야 한다.

@Query(value = "select p from Post p join fetch p.user",
        countQuery = "select count(p) from Post p join p.user")
Page<Post> findAllWithUser(Pageable pageable);

distinct + fetch join

  • Jpql에서의 distinct
    • SQL에 distinct를 추가
    • 엔티티 중복 제거
  • Fetch join에서 distinct를 사용하게 되면 데이터가 다르므로 SQL 결과에서 중복을 제거하지는 못하고 애플리케이션에서 중복 제거를 시도하여 같은 식별자를 가진 중복 엔티티를 제거한다.

일대다 fetch join

컬렉션 fetch join

  • 일대다 join(컬렉션 fetch join)을 사용할 경우 데이터가 예측할 수 없이 증가하기 때문에 페이징을 사용할 수 없다.
  • 컬렉션 둘 이상에 fetch join을 사용하면 안된다. 이는 데이터가 부정확하게 조회되는 문제를 발생시킬 수 있다.
  • 참고) ToOne 조인의 경우 페이징 쿼리에 영향을 주지 않으므로 문제 없이 페이징을 사용할 수 있다.

페이징 + 컬렉션 엔티티 조회

order를 페이징 처리하는데 orderItem 또한 필요한 경우

(1) ToOne 관계를 모두 fetch join 한다.
(2) 컬렉션을 지연 로딩으로 설정하되 hibernate.default_batch_fetch_size 또는 @BatchSize를 적용한다.

  • 쿼리 호출수를 1 + N에서 1 + 1로 최적화 된다.
  • 일대다 조인(컬렉션 조인을)의 경우 데이터가 뻥튀기가 되면서 전송되는 데이터량이 많아진다(데이터 중복 발생). 하지만 ToOne 관계는 모두 fetchjoin하고 컬렉션을 지연로딩하되 batch_size를 설정하는 방식을 통하여 데이터 전송량을 줄일 수 있다(데이터 중복 없음).
  • 페이징도 가능하게 한다.

hibernate.default_batch_fetch_size, @BatchSize

  • hibernate.default_batch_fetch_size: 글로벌 설정
  • @BatchSize: 개별 최적화
  • 컬랙션이나 프록시 객체를 한꺼번에 설정한 크기 만큼의 IN 쿼리로 조회한다.
    • 설정한 크기: IN 쿼리 안에 식별자 개수

      batch_size: 10, total_size: 100
      1번 -> IN 쿼리
      ...
      11번 -> IN 쿼리
      ...
      총 10번의 IN 쿼리가 발생한다.

  • batch_size는 100에서 1000 정도로 사용하자
    • In 쿼리의 파라미터가 1000이 넘으면 오류를 발생시키는 DB가 있다.
    • DB나 어플리케이션이 순간 부하를 어디까지 견딜 수 있는지로 결정하면 된다.

OSIV(Open Session In View)

  • "영속성 컨텍스트를 어느 범위까지 유지할 것인가?"에 대한 설정 항목이다.
  • 최적화를 위해 필요한 설정 사항이다.

OSIV ON

  • spring.jpa.open-in-view = true
  • 트랜잭션 시작시 데이터베이스 커낵션을 얻는다.
  • 트랜잭션이 끝나도 데이터베이스 커낵션과 영속성 컨텍스트를 반환하지 않고 api나 view 응답이 반환될 때까지 살려둔다.
  • 너무 오랜시간동안 데이터베이스 커낵션 리소스를 사용하기 때문에 실시간 트래픽이 중용한 어플리케이션에서는 커낵션이 모자랄 수 있다.
  • ADMIN에 적합하다.

OSIV OFF

  • spring.jpa.open-in-view = false
  • 트랜잭션 시작시 데이터베이스 커낵션을 얻는다.
  • 트랜잭션이 끝나면 데이터베이스 커낵션과 영속성 컨텍스트를 반환한다.
  • 데이터베이스 커낵션 리소스를 낭비하지 않으며 모든 지연 로딩을 트랜잭션 안에서 처리해야 한다.
  • 실시간 API에 적합하다.
profile
꾸준히 나아가자 🐢

0개의 댓글