[Hibernate] Query Plan Cache 옵션 수정하여, OutOfMemoryError 예방하기
문제
Hibernate 사용 시 Query Plan Cache 객체를 너무 많이 생성하면, OutOfMemoryError가 발생할 수 있다.
https://meetup.toast.com/posts/211
따라서 Hibernate Query Plan Cache 옵션을 설정하여, OutOfMemoryError를 예방할 수 있다.
https://medium.com/quick-code/what-a-recurring-outofmemory-error-taught-me-11f2061063a1
위의 링크의 일부 내용을 보면 다음과 같다.
Firstly, a couple of APIs are really complex and require hundreds of queries. Then, the query plan cache provided by Hibernate may be the culprit. By default, the maximum number of entries in the plan cache is 2048. An HQLQueryPlan object occupies approximately 3MB. ~3 * 2048 = ~6GB, and I the heap size is limited to 4GB…
위의 내용을 해석한 결과를 토대로 현재 운영되고 있는 Api에서도 충분히 OutOfMemoryError가 발생할 수 있다는 것을 알게 되었다. 현재 운영되고 있는 Api의 Heap 메모리 설정은 다음과 같다.
- -Xms4096m
- -Xmx4096m
위의 최대 Heap 메모리 사이즈에 따라 계산을 해봤는데, 아래의 결과를 도출할 수 있었다.
- HQL Query Plan : 3MB
- spring.jpa.properties.hibernate.query.plan_cache_max_size: 2048 (default)
- 3MB * 2048 = 6GB
2048개의 Query Plan Cach 객체를 생성하게 되면, 현재 운영하고 있는 Api는 반드시 OutOfMemoryError가 발생하게 된다.
해결 방법
위의 링크 내용을 토대로 아래와 같은 설정을 진행했다.
spring:
jpa:
properties:
hibernate:
query:
plan_cache_max_size: 1024
plan_parameter_metadata_max_size: 64
in_clause_parameter_padding: true
- plan_cache_max_size : 쿼리 계획 캐시의 최대 사이즈 (default: 2048)
- plan_parameter_metadata_max_size : Native Query ParameterMetadata 최대 사이즈 (default: 128)
- in_clause_parameter_padding : Where 조건에서 In절의 Padding Cache 사용 유무 (default: false)
https://kwonnam.pe.kr/wiki/java/hibernate/performance
또한 위의 링크를 통해 Hibernate 5.2.18 이후 버전에서는 in_clause_parameter_padding을 항상 true로 둘 것. 이라는 정보도 얻게 되었고, 현재 사용하는 Hibernate의 버전은 5.6.5 였기 때문에 in_clause_parameter_padding 값을 true로 적용했다.