페이징기능을 사용함에 있어 OneToMany 관계를 페치 조인하여 가져왔다더니 속도가 너무 안나오는 현상이 있었다. 30초 소요 그래서 찾아보니 일대다 조인시 전체 데이터를 조회하고 메모리에서 페이징을 하기 때문에 오래 걸린다.
컬렉션을 페치 조인 하면 페이징이 불가능하다
- 컬렉션을 페치 조인하면 일대다 조인이 발생하므로 데이터가 예측할 수 없이 증가한다.
- 일대다에서 일(1)을 기준으로 페이징을 하는 것이 목적이다. 그런데 데이터는 다(N)를 기준으로 row가 생성된다.
- Order를 기준으로 페이징 하고 싶은데, 다(N)인 OrderItem을 조인하면 OrderItem이 기준이 되어버린다.
- 더 자세한 내용은 자바 ORM 표준 JPA 프로그래밍 - 페치 조인 한계 참조)
이 경우 하이버 네이트는 경고 로그를 남기고 모든 DB 데이터를 읽어서 메모리에서 페이징을 시도한다. 최악의 경우 장애로 이어질 수 있다.
한계 돌파
그러면 페이징 + 컬렉션 엔티티를 함께 조회하려면 어떻게 해야 할까?
지금부터 코드도 단순하고, 성능 최적화도 보장하는 매우 강력한 방법을 소개 하겠다. 대부분의 페이징 + 컬렉션 엔티티 조회 문제는 이 방법으로 해결할 수 있다.
- 먼저 ToOne (OneToOne, ManyToOne) 관계를 모두 페치조인 한다. ToOne 관계는 row수를 증가시키지 않으므로 페이징 쿼리에 영향을 주지 않는다.
- 컬렉션은 지연로딩으로 조회한다.
- 지연 로딩 성능 최적화를 위해 `hibernate.default_batch_fetch_size`, `@BatchSize`를 적용한다
- hibernate.default_batch_fetch_size: 글로벌 설정
- @BatchSize: 개별 최적화
- 이 옵션을 사용하면 컬렉션이나, 프록시 객체를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회한다.
출저: 김영한 인프런 강의 실전! 스프링부트와 JPA활용
강의를 한번 구매 해놓으면 기간은 무제한이다 1년전 들었던 내용인데 까먹을때 마다 다시 들을 수 있어 정말 좋다.
'Programing > Spring Boot' 카테고리의 다른 글
| 스프링부트 Pageable 카운트 쿼리 분리 (0) | 2023.06.29 |
|---|---|
| Spring boot Data JPA 엔티티를 DTO로 조회하는 방법 (0) | 2023.06.28 |
| 코틀린 스프링부트 @RequestBody, @RequestParam, @PathVariable 사용법 (0) | 2023.06.21 |
| 스프링부트, 리액트 파일 업로드 (0) | 2023.06.21 |
| 코틀린으로 크롤링 하기 Jsoup 사용 (0) | 2023.05.27 |