Spring

[Spring] default_batch_fetch_size 대로 in쿼리가 나가지 않는 이유

퉁그리 2022. 1. 9. 02:28

개발을 하다가 이상한 상황을 봤다.

 

default_batch_fetch_size을 1000으로 설정했음에도 불구하고, in절이 62개의 리스트로만 가져오고 나눠서 가져오는 것이다.

 

버그인가 싶었는데 구글링을 해보니 이유를 찾았다. 역시 킹영한ㄷㄷ

 

보통 관계형 데이터베이스들은 select * from x where in (?), select * from x where in (?, ?) 같은 preparedstatement는 미리 문법을 파싱해서 최대한 캐싱을 해둔다.

 

그런데 default_batch_fetch_size가 1000이라면 최대 1000개의 preparedstatement을 준비해야한다.

select * from x where in (?)

select * from x where in (?, ?)

select * from x where in (?, ?, ?)

select * from x where in (?, ?, ? ...)

 

이렇게 되면 성능이 떨어지기 때문에 Hibernate는 이 문제를 해결하기 위해 2등분을 하며 최적화를 한다.

 

1000 = 설정값

500 = 1000/2

250 = 500/2

125 = 250/2

62 = 125/2

31 = 62/2

15 = 31/2

7 = 15/2...

 

이렇게 최적화를 하기 때문에 100개를 셀렉할 때, 62개, 31개, 7개로 끊어가져오는 이유가 여기 있었다.

 

너무너무 신기하다.

 

이 방법 외에 그냥 설정한대로 in을 전부하는 방법도 있긴하다.

spring.jpa.properties.hibernate.batch_fetch_style: dynamic

 

하지만 이방법은 최적화가 되지 않기 때문에 권장치는 않는다고 한다.

 

때문에 무작정 1000 이렇게 할게 아니라,

 

본인서비스의 최대 객체양이나 평균양을 고려해서 적정한 수치를 설정하는 것이 좋을 것같다.

 

 

출처 : 실전! Querydsl - 인프런 | 학습 페이지 (inflearn.com)