김영한의 스프링 부트와 JPA 활용2 - 페치 조인, 배치 OSIV

2025. 2. 11. 23:16·김영한의 스프링 부트와 JPA 활용2

Qestion

  • 성능 최적화 권장 순서를 설명하시오
  • OSIV에 대해 설명하시오

 

페치 조인으로 성능 최적화

  • 일대다의 경우 데이터 중복이 발생하므로 distinct 사용
  • 일대다와 같은 컬렉션 페치 조인을 사용하면 페이징이 불가능
  • 하이버네이트는 경고 로그를 남기면서 모든 데이터를 DB에서 읽어 오고 메모리에서 페이징 해버리는데 이는 매우 위험

 

엔티티를 DTO로 변환해서 페이징하기

  • 먼저 ToOne(1:1, 다:1) 관계를 모두 페치 조인(ToOne 관계는 row 수를 증가시키지 않아 페이징에 영향을 주지 않음)
  • 컬렉션은 지연 로딩으로 조회
    • 지연 로딩 성능 최적화 방법
    • hibernate.default_batch_fetch_size 로 글로벌 적용
    • @BatchSize로 필요한 곳에 적용
    • 이 옵션을 사용하면 컬렉션이나 프록시 객체를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회
    • 어떻게 내가 원하는 것만 미리 딱 개수만큼 가져오냐면 영속성 컨텍스트에 있는 내용을 기반으로 가져오기 때문
  • 장점
    • 쿼리 호출 수가 1 + N -> 1 + 1 이 됨
    • 조인보다 DB 데이터 전송량이 최적화 됨(조인은 중복 데이터 조회가 발생하기 때문)
    • 페치 조인과 비교해 쿼리 호출 수가 약간 증가 되지만 DB 데이터 전송량은 감소
    • 페이징이 가능함
  • 결론
    • 페이징이 필요할 경우 ToOne 관계 페치 조인으로 쿼리 수를 줄이고 나머지는 배치르 최적화

 

default_batch_fetch_size의 적정값

  • 일반적으로 100 ~ 1000 사용을 권함
  • 1000을 선택하면 성능이 가장 좋겠지만 순간 부하량이 증가할 수 있음
  • 애플리케이션단에서는 100이든 1000이든 어차피 다 불러와야 하므로 메모리 사용량은 같음
  • 부하를 견딜 수 있는 만큼 100~1000 에서 적정 값으로 설정 필요

 

성능 최적화 권장 순서

  • 엔티티 조회 방식으로 우선 접근
    • 페치 조인으로 쿼리 수 최적화
    • 컬렉션 최적화
      • 페이징 필요시 hibernate.default_batch_fetch_size 사용
      • 페이징 필요 없을 시 페치 조인 사용
  • 왠만하면 엔티티 조회 방식으로 처리가 되며 그렇지 않을 경우 DTO 조회 방식 사용
    • DTO 직접 조회시 네트워크 부하 줄일 수 있음
    • 컬렉션 조회 최적화 - 일대다 관계인 컬렉션은 IN 절을 활용해서 메모리에 미리 조회해서 최적화
    • 플랫 데이터 최적화 - JOIN 결과를 그대로 조회 후 애플리케이션에서 원하는 모양으로 직접 변환

 

OSIV(Open Session In View)

  • OSIV가 켜져 있으면 커넥션 시작 시점부터 API 응답이 끝날 때 까지 영속성 컨텍스트와 DB 커넥션을 유지함
  • 이 전략은 너무 오랜시간동안 데이터베이스 커넥션 리소스를 사용하기 때문에 실시간 트래픽이 중요한 애플리케이션에서는 커넥션이 모자라 장애로 이어질 수 있음
  • OSIV를 끄면 지연 로딩을 트랜잭션 안에서 모두 처리해야 함
  • 즉, 트랜잭션이 끝나기 전에 지연 로딩을 모두 강제로 호출해 줘야 함.
  • 트래픽이 많은 실시간 서비스에서는 OSIV를 끄고, ADMIN 처럼 커넥션을 많이 사용 하지 않는 곳에서는 켜는 방식 채택 가능

'김영한의 스프링 부트와 JPA 활용2' 카테고리의 다른 글

김영한의 스프링 부트와 JPA 활용2 - 조회 성능 최적화 방법  (0) 2025.02.10
'김영한의 스프링 부트와 JPA 활용2' 카테고리의 다른 글
  • 김영한의 스프링 부트와 JPA 활용2 - 조회 성능 최적화 방법
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      버퍼
      페치 조인
      Target
      @discriminatorcolumn
      양방향 맵핑
      프록시 팩토리
      jpq
      자바
      @discriminatorvalue
      스레드
      @within
      JPQL
      WAS
      requset scope
      typequery
      log trace
      hibernate5module
      Thread
      단방향 맵핑
      조회 성능 최적화
      락
      @args
      고급
      gesingleresult
      빈 후처리기
      김영한
      cglib
      reentarantlock
      프록시
      jdk 동적 프록시
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    김영한의 스프링 부트와 JPA 활용2 - 페치 조인, 배치 OSIV
    상단으로

    티스토리툴바