hibernate 6.x 에서 batch size의 전략 변경하기 아는 분 있으신가요?(batch_fetch_style deprecated issue)
https://www.inflearn.com/questions/34469위 링크를 참조해보면, 이전에 hibernate 의 batch size 기본전략이 legacy 임을 알 수 있습니다.하지만, 현재 사용 중인 hibernate 6.2 에서 @BatchSize 를 사용하면 기본적으로 dynamic 으로 조회되고 있습니다. 참고로 글로벌 설정으로 default_batch_fetch_size 를 설정해도 동일합니다. select
...
from
my_table m1_0
where
m1_0.id in(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
binding parameter [1] as [INTEGER] - [5]
binding parameter [2] as [INTEGER] - [1]
binding parameter [3] as [INTEGER] - [null]
...
binding parameter [98] as [INTEGER] - [null]
binding parameter [99] as [INTEGER] - [null]
binding parameter [100] as [INTEGER] - [null] 그래서 batch_fetch_style 을 직접 설정하려고 봤더니 hibernate 6.0 이후부터는 deprecated 되었고, MultiKeyLoadSizingStrategy 를 사용하라고 하네요. 혹시 이 MultiKeyLoadSizingStrategy 사용해보신 분 있으신가요?또는 다른 방법으로 batch size 전략을 이전의 기본전략인 legacy 처럼 변경하신 분이나 현재 프로젝트에서 비슷한 issue 겪으신 분 있으신가요?--(아까 오전에 비슷한 질문 올리면서, spring.jpa.properties.hibernate.jdbc.batch_size 사용하면 되는 것 같다고 했었는데 착각이었습니다. 실제로는 n + 1 발생에 영향을 주지 않습니다.)--(추가)MultiKeyLoadSizingStrategy 를 사용하는 부분은 Dialect 입니다. 이때 넘겨받는 numberOfKeys 는 지정한 BatchSize 와 동일합니다. 그리고 아래 코드에 의해 최종적으로 생성하는 ? 의 개수는 최초로 딱 1번, 1개만 생성되는 것처럼 보입니다. 그러면 코드가 dynamic 처럼 작동하는 게 이해는 가네요. 동적으로 id 의 개수에 따라 다른 PreparedStatement를 사용하는 게 아니니까요.만약 BatchSize 를 10으로 정한 필드가 있다면, 해당 필드는 아래 코드에 의해 10(pad=false, column=1) 또는 16(pad=true, column=1) 둘 중 하나의 쿼리만 생성됩니다.위에서 언급한 링크에서 김영한 님 설명대로라면 10 + nlog2 개의 쿼리가 생성되는 데 반해, MultiKeyLoadSizingStrategy 는 딱 하나의 쿼리만을 생성하고 재사용하는 것 같습니다. 그런데 그 쿼리의 ? 의 개수를 '잘' 정하는 거죠.그러면 pad와 numberOfColumns 를 어떻게 바꾸느냐도 알아봐야겠네요... 그리고 최적화에 대한 새로운 패러다임? 자체도 이해할 필요가 있어 보입니다. 아래는 Dialect 추상클래스의 일부분입니다. protected final MultiKeyLoadSizingStrategy STANDARD_MULTI_KEY_LOAD_SIZING_STRATEGY = (numberOfColumns, numberOfKeys, pad) -> {
numberOfKeys = pad ? MathHelper.ceilingPowerOfTwo( numberOfKeys ) : numberOfKeys;
final long parameterCount = (long) numberOfColumns * numberOfKeys;
final int limit = getParameterCountLimit();
if ( limit > 0 ) {
// the Dialect reported a limit - see if the parameter count exceeds the limit
if ( parameterCount >= limit ) {
return limit / numberOfColumns;
}
}
return numberOfKeys;
};--(추가)pad 설정은 아래와 같이 하면 됩니다. 기본값은 false 인 것 같네요.spring.jpa.properties.hibernate.query.in_clause_parameter_padding=true그리고, numberOfColumns 는 굳이 건드려야 할 필요는 없어보입니다.--결론적으로 batch_fetch_style 이 deprecated 된 이후에는 기존의 legacy 처럼 여러 개의 statement 를 만들어서 사용하지 못 하고, 각 Entity 의 batch size 를 얼마나 설정하느냐에 따라 Dialect가 그에 대응하는 딱 하나의 statement 를 만드는 것 같습니다.