인프런 커뮤니티 질문&답변

roman14님의 프로필 이미지
roman14

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파

default_batch_fetch_size, @BatchSize 가 동작하지 않습니다.

작성

·

1K

0

강의 내용 중 N+1, 페이징 등의 복합적인 문제를 해결하기 위해 BatchSize 기능을 이용하는데 해당 기능이 동작하질 않아 질문을 드립니다.

 

  • 스프링부트 설정 파일에 설정한 값은 아래와 같습니다.

# application.yml
spring:
  jpa:
    hibernate:
      ddl-auto: create
      properties:
        hibernate:
          default_batch_fetch_size: 30
          jdbc:
            batch_size: 100

 

  • 강의 예시대로라면 아래와 같이 orderItem을 조회할 때에 IN 조건이 발생되어 총 두 번의 쿼리가 나가야 하지만, 실제로는 IN 조건이 생성되지 않고 BatchSize 설정 전과 같이 여전히 N+1 문제가 해결되지 않는 모습입니다.

2022-11-15 05:11:32.146  INFO 19268 --- [io-49445-exec-5] p6spy                                    : 2022-11-15T05:11:32.146352400 / time:0ms / 
    select
        order0_.order_id as order_id1_10_0_,
        member1_.member_id as member_i1_6_1_,
        delivery2_.delivery_id as delivery1_4_2_,
        order0_.delivery_id as delivery4_10_0_,
        order0_.member_id as member_i5_10_0_,
        order0_.order_date as order_da2_10_0_,
        order0_.status as status3_10_0_,
        member1_.add_time as add_time2_6_1_,
        member1_.city as city3_6_1_,
        member1_.street as street4_6_1_,
        member1_.zipcode as zipcode5_6_1_,
        member1_.description as descript6_6_1_,
        member1_.name as name7_6_1_,
        delivery2_.city as city2_4_2_,
        delivery2_.street as street3_4_2_,
        delivery2_.zipcode as zipcode4_4_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 limit 50 offset 1
2022-11-15 05:11:32.147  INFO 19268 --- [io-49445-exec-5] p6spy                                    : 2022-11-15T05:11:32.147842300 / time:0ms / 
    select
        orderitems0_.order_id as order_id5_9_1_,
        orderitems0_.order_item_id as order_it1_9_1_,
        orderitems0_.order_item_id as order_it1_9_0_,
        orderitems0_.count as count2_9_0_,
        orderitems0_.item_id as item_id4_9_0_,
        orderitems0_.order_id as order_id5_9_0_,
        orderitems0_.order_price as order_pr3_9_0_ 
    from
        order_item orderitems0_ 
    where
        orderitems0_.order_id=11
2022-11-15 05:11:32.148  INFO 19268 --- [io-49445-exec-5] p6spy                                    : 2022-11-15T05:11:32.148833600 / time:0ms / 
    select
        item0_.item_id as item_id2_5_0_,
        item0_.name as name3_5_0_,
        item0_.price as price4_5_0_,
        item0_.stock_quantity as stock_qu5_5_0_,
        item0_1_.author as author1_0_0_,
        item0_1_.isbn as isbn2_0_0_,
        item0_2_.actor as actor1_7_0_,
        item0_2_.director as director2_7_0_,
        item0_3_.artist as artist1_8_0_,
        item0_3_.etc as etc2_8_0_,
        item0_.dtype as dtype1_5_0_ 
    from
        item item0_ 
    left outer join
        book item0_1_ 
            on item0_.item_id=item0_1_.item_id 
    left outer join
        movie item0_2_ 
            on item0_.item_id=item0_2_.item_id 
    left outer join
        music item0_3_ 
            on item0_.item_id=item0_3_.item_id 
    where
        item0_.item_id=9
2022-11-15 05:11:32.149  INFO 19268 --- [io-49445-exec-5] p6spy                                    : 2022-11-15T05:11:32.149825900 / time:0ms / 
    select
        item0_.item_id as item_id2_5_0_,
        item0_.name as name3_5_0_,
        item0_.price as price4_5_0_,
        item0_.stock_quantity as stock_qu5_5_0_,
        item0_1_.author as author1_0_0_,
        item0_1_.isbn as isbn2_0_0_,
        item0_2_.actor as actor1_7_0_,
        item0_2_.director as director2_7_0_,
        item0_3_.artist as artist1_8_0_,
        item0_3_.etc as etc2_8_0_,
        item0_.dtype as dtype1_5_0_ 
    from
        item item0_ 
    left outer join
        book item0_1_ 
            on item0_.item_id=item0_1_.item_id 
    left outer join
        movie item0_2_ 
            on item0_.item_id=item0_2_.item_id 
    left outer join
        music item0_3_ 
            on item0_.item_id=item0_3_.item_id 
    where
        item0_.item_id=10

 

  • 엔티티 클래스의 컬렉션 필드에 @BatchSize를 직접 입력해보았지만 결과는 같았습니다.

 

  • 커뮤니티 질문 중 @Transactional 설정으로 인한 flush 발생 여부에 따라 동작이 상이할 수 있다는 내용을 보고 @Transactional(readonly = true) 설정도 해보았지만 결과는 같았습니다.

 

전체 프로그램 소스코드 다운로드) https://drive.google.com/file/d/1Q0XQFEBGpAVi0xYhEZgr8qME4rebI39q/view?usp=share_link

답변 1

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. roman14님

application.yml에서 띄어쓰기가 잘못되어 있습니다. (이게 은근 실수가 많습니다^^)

기존에는 spring.jpa.hibernate.properties.hibernate로 되어 있었는데요.

원본

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/test
    username: sa
    password:
    driver-class-name: org.h2.Driver
  jpa:
    hibernate:
      ddl-auto: create
      properties:
        hibernate:
          default_batch_fetch_size: 30
          jdbc:
            batch_size: 100

 

다음과 같이 spring.jpa.properties.hibernate 이렇게 들어가야 합니다.

수정본

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/test
    username: sa
    password:
    driver-class-name: org.h2.Driver
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        default_batch_fetch_size: 30
        jdbc:
          batch_size: 100

감사합니다.

roman14님의 프로필 이미지
roman14
질문자

이 문제 해결한다고 며칠을 헤맸는데, 굉장히 한심한 실수였네요... 피드백 감사합니다!

roman14님의 프로필 이미지
roman14
질문자

설정이 제대로 적용되지 않아서 동작하지 않았으리라는 추측도 해보았었지만, 런타임에서 설정된 값을 호출하는 방법을 몰라서 확인을 해보지 못했던 것이 기억나는데 혹시 위와 같이 yml, properties를 통한 JPA, 하이버네이트 설정 값을 런타임에서 확인할 방법은 없을까요?

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. roman14님

스프링 부트 actuator에 env라는 항목을 찾아보시면 도움이 되실거에요.

감사합니다.

roman14님의 프로필 이미지
roman14

작성한 질문수

질문하기