join fetch
를 통해서 (inner join등 명시) N + 1 대신에 미리 join 문으로 객체를 로딩할 수 있다.@BatchSize
나 default_batch_size
를 지정하고, join fetch 보다는 Hibernate.initialize(lazy로딩객체)
형태를 사용하는게 더 나을 수 있다. 이 경우에는 1+1 번 조회가 나가는 편이다(batch size에 따라 달라짐. batch size 단위로 조회 반복).hibernate.query.fail_on_pagination_over_collection_fetch=true
옵션을 켜서 미리 에러를 내고 확인해서 고쳐두는게 좋다.
batch-size
설정은 OneToMany 등의 관계에서 Many쪽 Lazy Proxy 객체를 로딩할때, 한번에 로딩할 갯수를 지정한다.
예를들면 Cat 객체가 Kitten 객체의 리스트를 Lazy로 가지고 있을 때 List<Cat>
을 돌면서 getKittens()
를 실행하면 각각의 Cat에 대해 한번씩 쿼리가 날라간다.(n + 1 problem)
하지만 @BatchSize(size = 10)
처럼 해당 관계에 설정을 해 두면, Kitten 객체를 로딩할 때 Cat id 10개씩 in
Query로 한번에 로딩한다.
hibernate.default_batch_fetch_size=30
프라퍼티 형태로 일괄 지정도 가능하다.128
은 넘기지 말자. 128
을 넘기는 순간 2^n
에 증가 규칙에 의해 256
개로 증가해버린다.> In the first case, hibernate.jdbc.fetch_size sets the statement's fetch size within the JDBC driver, that is the number of rows fetched when there is more than a one row result on select statements. In the second case, hibernate.jdbc.batch_size determines the number of updates (inserts, updates and deletes) that are sent to the database at one time for execution.
fetch_size
는 result 가 여러개일 때, 한 번에 읽어올 row 수이고(단,MySQL은 항상 전체 데이터를 한방에 읽는다고함. TBD)batch_size
는 update(insert,update,delete) 시에 묶어서 요청할 갯수이다.hibernate.query.in_clause_parameter_padding=true
항상 true
로 둘 것.IN
절 쿼리에 대해서 2의 제곱단위로 쿼리를 생성한다.IN
절 쿼리가 QueryPlanCache
를 모두 점유해서 메모리가 부족해질수 있고, 메모리가 남아돌더라도 캐시를 모두 IN
절이 점유해버리므로 별로 좋지 못하다.
특히 200 개 기준인게 보통인데, in_clause_parameter_padding
은 2^n 단위로 증가하므로 128개를 초과하면 in 파라미터가 그 다음인 256 개가 돼 버리면서 인덱스를 안타게 될 수 있다.
in 에 들어가는 값이 128 을 초과하지 않게 파티셔닝하고 관리하는게 좋다. @BatchSize
, hibernate.default_batch_fetch_size
도 참조.
eq_range_index_dive_limit
: default 200 개 초과시 index 안탐.range_optimizer_max_mem_size
: default 8mb 초과시 index 안탐.hibernate.query.plan_cache_max_size
기본값은 2048
이다.auto commit=false
을 항상 켜고, Hibernate 에서 직접 auto commit=false
하는 것을 막아서 불필요한 setAutoCommit()
호출로 인한 성능 저하를 줄이기
auto commit=false 이면서 Spring Data 사용시 제대로 Transaction이 안 걸려 있으면 오동작이 발생한다.
모든 Repository 인터페이스와 Custom 구현에 @Transactional
을 붙여주어야 한다.
auto-commit: false
로 지정. 이걸 true
로 해버리면 트랜잭션이 안 먹음.hibernate.connection.provider_disables_autocommit: true
로 지정 : 커넥션 풀의 autocommit 을 무조건 따르겠다는 의미. 5.2.10
이상 버전auto-commit
설정값에 따라 자동으로 hibernate.connection.provider_disables_autocommit: true
설정을 해준다. HibernateJpaConfiguration.java
if (!vendorProperties.containsKey(PROVIDER_DISABLES_AUTOCOMMIT)) { configureProviderDisablesAutocommit(vendorProperties); } ... if (isDataSourceAutoCommitDisabled() && !isJta()) { vendorProperties.put(PROVIDER_DISABLES_AUTOCOMMIT, "true"); }
in Hibernate 5.2.10, we introduced the hibernate.connection.provider_disables_autocommit configuration property which tells Hibernate that the underlying JDBC Connections already disabled the auto-commit mode.