[API 개발 고급] ❗지연 로딩과 조회 성능 최적화(V3) 3/4
2022. 5. 25. 19:16ㆍJava/JPA
간단한 주문 조회 V3: 엔티티를 DTO로 변환 (fetch join 사용 O)
결론 : fetch join으로 쿼리 1번 호출
V2에서 발생한 성능 문제(N+1)를 해결하기 위해서
페치 조인을 사용해보겠습니다.
❗ [중요] ❗
실무에서 JPA 성능 문제의 90%는 N+1에서 발생하고
페치 조인은 성능 최적화를 위해서 자주 사용하기때문에 100% 이해하고 있어야 합니다.
OrderSimpleApiController
package jpabook.jpashop.api;
/**
* @XToOne 관계(ManyToOne, OneToOne에서의 성능최적화)
* Order
* Order -> Member
* Order -> Delivery
*/
@RestController
@RequiredArgsConstructor
public class OrderSimpleApiController {
private final OrderRepository orderRepository;
@GetMapping("/api/v3/simple-orders")
public List<SimpleOrderDto> ordersV3() {
List<Order> orders = orderRepository.findAllWithMemberDelivery();
return orders.stream()
.map(o -> new SimpleOrderDto(o))
.collect(Collectors.toList());
}
@Data
static class SimpleOrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address; //배송지 주소
//생성자
public SimpleOrderDto(Order order) {
orderId = order.getId();
name = order.getMember().getName(); //LAZY 초기화
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress(); //LAZY 초기화
}
}
}
OrderRepository 추가
/**
* 지연 로딩과 조회 성능 최적화(V3) - 페치 조인
* 지연 로딩, 프록시 무시하고 진짜 객체의 값을 채워서 가져옴
*/
public List<Order> findAllWithMemberDelivery() {
return em.createQuery(
"select o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d", Order.class)
.getResultList();
}
Postman확인
V2와 V3는 결과는 같지만 쿼리 수가 다릅니다.
V3에서는
쿼리가 1번 나간 것을 확인할 수 있습니다.
/* select o from Order o join fetch o.member m join fetch o.delivery d */
select
order0_.order_id as order_id1_6_0_,
member1_.member_id as member_i1_4_1_,
delivery2_.delivery_id as delivery1_2_2_,
order0_.delivery_id as delivery4_6_0_,
order0_.member_id as member_i5_6_0_,
order0_.order_date as order_da2_6_0_,
order0_.status as status3_6_0_,
member1_.city as city2_4_1_,
member1_.street as street3_4_1_,
member1_.zipcode as zipcode4_4_1_,
member1_.name as name5_4_1_,
delivery2_.city as city2_2_2_,
delivery2_.street as street3_2_2_,
delivery2_.zipcode as zipcode4_2_2_,
delivery2_.status as status5_2_2_
from
orders order0_
inner join
member member1_
on order0_.member_id=member1_.member_id
inner join
delivery delivery2_
on order0_.delivery_id=delivery2_.delivery_id
정리
엔티티를 페치 조인(fetch join)을 사용해서 쿼리 1번에 조회
페치 조인으로 order -> member , order -> delivery는 이미 조회된 상태 이므로 지연 로딩 X
페치 조인은 실무에서 자주 사용하므로 꼭 알고 있어야 합니다.
'Java > JPA' 카테고리의 다른 글
[API 개발 고급] 컬렉션 조회 최적화(페치 조인, 페이징) (0) | 2022.05.26 |
---|---|
[API 개발 고급] 지연 로딩과 조회 성능 최적화(V4) 4/4 (0) | 2022.05.26 |
[API 개발 고급] 지연 로딩과 조회 성능 최적화(V2) 2/4 (0) | 2022.05.25 |
[API 개발 고급] 지연 로딩과 조회 성능 최적화(V1) 1/4 (0) | 2022.05.25 |
영속성 전이(CASCADE)와 고아 객체 (0) | 2022.05.25 |