hibernate 6.x 에서 batch size의 전략 변경하기 아는 분 있으신가요?(batch_fetch_style deprecated issue)

23.08.18 12:24 작성 23.08.22 19:42 수정 조회수 731

0

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 를 만드는 것 같습니다.

답변 2

·

답변을 작성해보세요.

0

psam1017님의 프로필

psam1017

질문자

2023.08.22

https://www.inflearn.com/questions/903628
--
위 질문과 관련이 있는 내용 같습니다. 답변도 위 질문의 김영한 님 답변에 포함되어 있습니다.

결론적으로 hibernate 6.2 이후부터는 여러 개의 statement 를 캐싱하지 않음으로 성능 최적화를 구현하고 있고, default_batch_fetch_size 만큼의 ? 가 생성되고, null 이 들어가는 것은 자연스러운 현상(?)이니 그냥 내버려두면 되는 것 같습니다.

자세한 원리나 이유가 궁금하신 분은 위 링크 참고하시기 바랍니다.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.08.19

안녕하세요, 인프런 AI 인턴이에요.

Hibernate 6.x에서 batch size 전략을 변경하는 방법에 대해 찾아보셨군요.
Hibernate 6.0 이후에는 batch_fetch_style이 deprecated되었다고 하네요.
그래서 MultiKeyLoadSizingStrategy를 사용하라고 추천하고 있는데요.

MultiKeyLoadSizingStrategy를 사용해보신 분이 있는지, 또는 다른 방법으로 batch size 전략을 이전의 기본전략인 legacy로 변경하는 방법을 아시는 분이 계신지에 대한 질문이시죠.

제가 답변을 드리기 전에, 해당 질문에 대한 답변과 관련된 내용은 현재 제가 가지고 있는 정보에는 없어 보입니다. 따라서, 해당 내용에 대해 자세하게 설명해드릴 수는 없어요.

그러나, Hibernate의 최신 버전과 관련된 공식 문서나 포럼에서 관련 정보나 예시 코드를 찾아보시는 것이 좋을 것 같습니다. Hibernate의 공식 사이트나 Hibernate 커뮤니티에서 자세한 내용을 찾아보시면 도움이 될 수 있습니다.

또한, 제가 답변을 드리는 이 채널은 프로그래밍과 인프런에 관련된 질문에 답변하는 곳이기 때문에, 개발과 관련된 질문에 한해서만 답변이 가능하니 참고해주세요.

더 도움을 드리지 못해 죄송합니다. 다른 질문이 있으시면 언제든지 물어보세요. 감사합니다.