본문 바로가기
Spring/JPA

[JPA] Hibernate Batch Size 설정

by 코딩균 2022. 3. 9.

Batch Size?

1:N 관계 ( 여기서는 Order : OrderItem 이라고 가정 )에서의 지연 로딩 시에 SQL 문이 각각의 N개의 객체에 대해서 

select 
	orderItem0_.order_item_id as order_item_id5_5_1_,
    orderItem0_.order_id as order_id_it1_5_1_,
    orderItem0_.item_id as item_id_it1_5_0,
    orderItem0_.order_price as order_price_id5_5_0,
    orderItem0_.count as count_id5_3_0
from 
	orderItem orderItem0_
where
	orderitem0_.order_id = ?

where 절에 = 이 들어가서 N개의 SQL이 나가서 orderItem을 가져오게 만드는 기본 hibernate 설정을

where 절에 IN 을 사용하여 1개의 SQL문으로 쿼리 수를 최적화 되도록 설정해주는 것이다

과장해보자면 비슷한 조회 쿼리 데이터를 한방 쿼리로 만들 수 있다

select 
	orderItem0_.order_item_id as order_item_id5_5_1_,
    orderItem0_.order_id as order_id_it1_5_1_,
    orderItem0_.item_id as item_id_it1_5_0,
    orderItem0_.order_price as order_price_id5_5_0,
    orderItem0_.count as count_id5_3_0
from 
	orderItem orderItem0_
where
	orderitem0_.order_id in (
    	?, ? # 1관계인 order의 개수
    )

IN 안에 들어가는 element의 개수가 Batch Size이다

 

정리하자면 적절한 상황에서 쿼리 수를 줄이기 위해 SQL 구문의 IN이 필요하다면 Batch Size 설정을 해주면 된다.

 

size 크기 설정

size가 100 인 경우 IN 안에 100개씩 끊어서 넣게된다

예를 들어 Order가 200개라면 

  • id 0 ~ id 99 까지 IN -> SQL 1번
  • id 100 ~ 199 까지 IN -> SQL 1번

(정확하게 100개씩 끊어서 넣지는 않는다고 한다 JPA가 내부적으로 최적화된 size를 판단하고 100만 넘지 않는다는게 batch size)

 

Batch Size의 크기는 사용하고 있는 DB가 얼마나 견딜 수 있는가를 판단하여 결정

application 메모리에는 결국 다 가져와야해서 상관이 없지만 

IN 절 안에 있는 element와 관련된 모든 data 들을 DB가 처리해야 하므로 결국, DB의 성능에 따라 결정

 

인프런 갓영한님 강의에서는 sizesms 100 ~ 1000 사이를 추천한다고 함

( DB의 종류에 따라 IN 절의 size를 최대 1000개로 제한하는 DB도 있다고 함)

 

 

적용 방법

global 하게 적용 to application.yml

jpa.properties.hibernate 에 default_batch_fetch_size를 설정해준다

이에 따라 모든 지연 로딩 프록시 객체를 만나면 100 사이즈로 IN SQL을 써서 가져온다

  jpa:
    hibernate:
      ddl-auto: create # create 인 경우 계속 data를 drop 시킴 / none 계속 data를 drop시키지 않음
    properties:
      hibernate:
#        show_sql: true <-운영환경에서는 system out이 아닌 다 log를 통해 찍어야 함
        format_sql: true
        default_batch_fetch_size: 100

 

Entity에 적용

N (여기서는 OrderItem) 대상인 entity에 적용해준다

해당 entity를 부를 때만 batch size가 적용된 IN SQL로 가져온다

@BatchSize(size = 100)
@Entity
public class OrderItem{
	...
}

 

Field에 적용

1 (여기서는 Order) 대상인 entity의 @OneToMany field 에 적용한다

Order에서 해당 collection을 가져올 때, batch size가 적용되어 IN SQL로 가져올것이다

@Entity
@RequiredArgsContructor
public class Order{
	...
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();
    
 }

 

Batch Size 설정은 1:N 컬렉션 조인에서 

1 + N (사실상 이런 것이 N+1 문제) 으로 나갈 수 있는 SQL 쿼리의 수를

1 : 1 로 줄여주니 좋은 것이다!!

 

N+1관련한 fetch join 과 문제 해결 방법은 아래에 다른 포스팅을 첨부한다

https://codinggyun.tistory.com/101

 

[JPA] 1:N / N:1 상황에서의 N+1 문제 해결 (Fetch Join ~ 지연로딩/Batch Size)

DB의 테이블이 위와 같은 관계를 가지고 있는 경우 N+1 문제 고려하지 않은 코드 ( DB n:1의 관계 ) data 가정 Order가 2개 존재 각각의 order와 연결된 member는 모두 다른 사람 모든 entity fetchType 은 LAZY -..

codinggyun.tistory.com