Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

지연로딩과 성능최적화(DTO, N+1) 본문

인프런/[인프런] Springboot와 JPA활용 2

지연로딩과 성능최적화(DTO, N+1)

Seung__ 2021. 8. 22. 23:07

1. DTO 로 변환해서 리턴.


  @GetMapping("/api/v2/simple-orders")
    public List<SimPleOrderDto> odersV2(){

        List<Order> orders = orderRepository.findAllByString(new OrderSearch());
        List<SimPleOrderDto> result = orders.stream()
                .map(o -> new SimPleOrderDto(o)) //map은 a를 b로 바꾸는 것.
                .collect(Collectors.toList());

        return result;
    }

    @Data
    private class SimPleOrderDto {

        private Long orderId;
        private String name;
        private LocalDateTime orderDate;
        private OrderStatus orderStatus;
        private Address address;

        public SimPleOrderDto(Order order){
            this.orderId = order.getId();
            this.name = order.getMember().getName(); //Member프록시객체 초기화
            this.orderDate = order.getOrderDate();
            this.orderStatus = order.getStatus();
            this.address = order.getDelivery().getAddress(); // Delivery 프록시객체 초기화
        }
    }
  • DTO로 반환을 했다.
  • 엔티티가 바뀌면 컴파일 오류가 발생해서 문제는 사전에 방지 가능.
  • 엔티티가 외부로 노출되지 않음

  • 무적권 DTO로 바꾸자.

 

2. LAZY로딩으로 인한 쿼리가 너무 많이 호출됨.. N+1 이슈


  • Order를 불러오면, Member, Delivery 정보도 같이 가져와야 한다.
  • 즉 Order 조회하는 쿼리 외에도 Member, Delivery 조회하는 쿼리도 나가야 한다.
Hibernate: 
    select
        order0_.order_id as order_id1_6_,
        order0_.delivery_id as delivery4_6_,
        order0_.member_id as member_i5_6_,
        order0_.order_date as order_da2_6_,
        order0_.status as status3_6_ 
    from
        orders order0_ 
    inner join
        member member1_ 
            on order0_.member_id=member1_.member_id limit ?
            
 Hibernate: 
    select
        member0_.member_id as member_i1_4_0_,
        member0_.city as city2_4_0_,
        member0_.street as street3_4_0_,
        member0_.zipcode as zipcode4_4_0_,
        member0_.name as name5_4_0_ 
    from
        member member0_ 
    where
        member0_.member_id=?
        
 Hibernate: 
    select
        delivery0_.delivery_id as delivery1_2_0_,
        delivery0_.city as city2_2_0_,
        delivery0_.street as street3_2_0_,
        delivery0_.zipcode as zipcode4_2_0_,
        delivery0_.status as status5_2_0_ 
    from
        delivery delivery0_ 
    where
        delivery0_.delivery_id=?
        
        
Hibernate: 
    select
        member0_.member_id as member_i1_4_0_,
        member0_.city as city2_4_0_,
        member0_.street as street3_4_0_,
        member0_.zipcode as zipcode4_4_0_,
        member0_.name as name5_4_0_ 
    from
        member member0_ 
    where
        member0_.member_id=?
        
        
Hibernate: 
    select
        delivery0_.delivery_id as delivery1_2_0_,
        delivery0_.city as city2_2_0_,
        delivery0_.street as street3_2_0_,
        delivery0_.zipcode as zipcode4_2_0_,
        delivery0_.status as status5_2_0_ 
    from
        delivery delivery0_ 
    where
        delivery0_.delivery_id=?
  • 와 근데 무슨 퀄리가 5번이나 나감???
  • Order조회하는 쿼리 -> Order 2개 조회됨 --> 각각 Member, Delivery 조회 쿼리
  • 총 5번의 쿼리.
  • 즉! Orders를 조회하는 쿼리 1번으로 인해 N번의 쿼리가 추가로 실행되었다.

참고로 지연로딩은 영속성 컨텍스트에서 조회하므로, 이미 조회한 경우 쿼리를 생략함 ㅎ

 

 

3. GitHub : 210822 N+1, LAZY LOADING


 

GitHub - bsh6463/SpringBootJPA1

Contribute to bsh6463/SpringBootJPA1 development by creating an account on GitHub.

github.com

 

Comments