킹의 개발일지

[JPA] 데이터 조회 시, 성능 향상 고려 사항 본문

JPA

[JPA] 데이터 조회 시, 성능 향상 고려 사항

k1ng 2022. 6. 8. 15:36

최근 쇼핑몰 프로젝트 책을 공부하면서 JPA를 사용하던 중, for 문을 순회하면서 데이터 조회 메서드를 호출 할 때마다 조회 쿼리문이 추가로 실행되는것을 봤다.

@Transactional(readOnly = true)
public Page<OrderHistDto> getOrderList(String email, Pageable pageable){

    List<Order> orders = orderRepository.findOrders(email, pageable);
    Long totalCount = orderRepository.countOrder(email);

    List<OrderHistDto> orderHistDtos = new ArrayList<>();

    for (Order order : orders){
        OrderHistDto orderHistDto = new OrderHistDto(order);
        List<OrderItem> orderItems = order.getOrderItemList();
        for (OrderItem orderItem : orderItems){
            // 해당 아이템의 대표이미지 가져오기.
            ItemImg itemImg = itemImgRepository.findByItemIdAndRepimgYn(orderItem.getItem().getId(), "Y");
            OrderItemDto orderItemDto = new OrderItemDto(orderItem, itemImg.getImgUrl());
            orderHistDto.addOrderItemDto(orderItemDto);
        }
        orderHistDtos.add(orderHistDto);
    }

    return new PageImpl<OrderHistDto>(orderHistDtos, pageable, totalCount);
}

하나의 order_id에 하나의 주문번호가 조건으로 설정 돼있다.
orders 테이블, 총 세개의 order row가 있다.
Orders 테이블은 OrderItem 테이블의 order_id 칼럼과 조인한다.

 

orders의 사이즈에 따라, List orderItems = order.getOrderItems() 해당 코드 때문에 위 쿼리문이 총 세번 반복된다.

 

(WHERE order_id = 90, WHERE order_id = 92, WHERE order_id = 94 총 세번) 만약 orders의 사이즈가 100이었다면 100번의 쿼리문이 더 실행 될것이고 db에 100번이나 접근하는것이다.

 

만약 orders의 주문 아이디를 'WHERE order_id IN(90, 92, 94)' 처럼 IN을 이용해 한번에 조회할 수 있다면 세번 실행될 쿼리가 한번으로 단축될 수 있다.

 

이때 "default_batch_fetch_size" 옵션을 사용해서 성능을 향상시킬수 있다.

 

즉, 옵션으로 지정한 사이즈만큼 한 번에 조회할 수 있다. 

 

 jpa:
    properties:
      hibernate:
        default_batch_fetch_size: 1000

 

 

application.yml 파일에서 다음과 같이 설정을 추가하고 구매이력을 조회하면 설정으로 준 사이즈까지는 IN 쿼리를 실행해주는것을 볼 수 있다.

 

JPA를 사용하다보면 N+1문제를 많이 접한다.

 

충분한 공부 없이 JPA를 사용한다면 성능상 이슈가 많이 생길듯 하다.

 

JPA를 단순히 많이 쓰이고 있는 표준이라해서 배움없이 사용하지 말고 충분히 공부하고 난후에 사용해야겠다는 생각이 든다. 

'JPA' 카테고리의 다른 글

@MappedSuperclass  (0) 2022.06.04