사용자 도구

사이트 도구


java:hibernate:performance

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판 이전 판
다음 판
이전 판
java:hibernate:performance [2017/11/30 21:48]
kwon37xi
java:hibernate:performance [2024/03/04 12:47] (현재)
kwon37xi [@org.hibernate.annotations.BatchSize]
줄 4: 줄 4:
   * [[java:hibernate:cache|Hibernate Cache]] - [[java:jpa:cache|JPA Second Level Cache]]   * [[java:hibernate:cache|Hibernate Cache]] - [[java:jpa:cache|JPA Second Level Cache]]
   * [[java:hibernate:batch|Hibernate Batch/Bulk Insert/Update]]   * [[java:hibernate:batch|Hibernate Batch/Bulk Insert/Update]]
 +  * [[java:jpa:entitygraph|JPA @EntityGraph]]
 +
  
 ===== Hibernate 성능 분석 ===== ===== Hibernate 성능 분석 =====
-  * ''hibernate.generate_statistics=true'' 로 설정하고 +  * [[java:hibernate:statistics|Hibernate Statistics]] 
-  * ''org.hibernate.stat''을 ''DEBUG''드로 둘 것.+  * [[java:quickperf|QuickPerf]] 로 lazy loading 발생여부 확인 가능(실제로는 쿼리가 날라간 갯수를 테스트 코드로 검증가능)
  
 +===== N+1 =====
 +  * [[https://github.com/adgadev/jplusone|adgadev/jplusone: Tool for automatic detection and asserting "N+1 SELECT problem" occurences in JPA based Spring Boot Java applications and finding origin of JPA issued SQL statements in general]]
 +  * https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping/39696775?stw=2#39696775
 +  * [[https://github.com/vladmihalcea/db-util/tree/master/scripts/ramdisk/windows|vladmihalcea/db-util: If you are using JPA and Hibernate, this tool can auto-detect N+1 query issues during testing.]]
 +
 +===== Join Fetch =====
 +  * JPQL 에서 ''join fetch''를 통해서 (inner join등 명시) N + 1 대신에 미리 join 문으로 객체를 로딩할 수 있다.
 +  * 하지만 **1:N 관계에서 1측이 N 만큼 반복 조회되는 문제가 있다. 실제 엔티티 객체가 여러개 생성된다.**
 +  * **limit 을 걸더라도 limit 이 DB에 걸리지 않고 모두 조회후 메모리에 걸리게 된다.**
 +  * 따라서 ''@BatchSize''나 ''default_batch_size'' 를 지정하고, join fetch 보다는 ''Hibernate.initialize(lazy로딩객체)'' 형태를 사용하는게 더 나을 수 있다. 이 경우에는 1+1 번 조회가 나가는 편이다(batch size에 따라 달라짐. batch size 단위로 조회 반복).
 +  * see [[java:hibernate:gotchas|Hibernate/JPA Gotcha]]
 +  * [[java:hibernate:configuration|Hibernate Configurations]] - ''hibernate.query.fail_on_pagination_over_collection_fetch=true'' 옵션을 켜서 미리 에러를 내고 확인해서 고쳐두는게 좋다.
 ===== @org.hibernate.annotations.BatchSize ===== ===== @org.hibernate.annotations.BatchSize =====
 ''batch-size'' 설정은 **OneToMany** 등의 관계에서 Many쪽 Lazy Proxy 객체를 로딩할때, 한번에 로딩할 갯수를 지정한다. ''batch-size'' 설정은 **OneToMany** 등의 관계에서 Many쪽 Lazy Proxy 객체를 로딩할때, 한번에 로딩할 갯수를 지정한다.
줄 15: 줄 29:
 하지만 ''@BatchSize(size = 10)'' 처럼 해당 관계에 설정을 해 두면, Kitten 객체를 로딩할 때 Cat id 10개씩 ''**in**'' Query로 한번에 로딩한다. 하지만 ''@BatchSize(size = 10)'' 처럼 해당 관계에 설정을 해 두면, Kitten 객체를 로딩할 때 Cat id 10개씩 ''**in**'' Query로 한번에 로딩한다.
  
-  * ''hibernate.default_batch_fetch_size=100'' 프라퍼티 형태로 일괄 지정도 가능하다. +  * ''hibernate.default_batch_fetch_size=30'' 프라퍼티 형태로 일괄 지정도 가능하다. 
-  * OneToOne Eager 에 대해서는 작동하지 않았다.+  * OneToOne, ManyToOne  Eager 에 대해서는 작동하지 않았다. 
 +  * 지나치게 큰 값을 설정하지 말아야 한다. 30개 정도가 적당해 보이며, 쿼리 실행시간이 수십 밀리세컨드 이내로 끝날 수준으로 정하는게 좋다. ''128''은 넘기지 말자. ''128''을 넘기는 순간 ''2^n''에 증가 규칙에 의해 ''256''개로 증가해버린다.
  
 ===== hibernate.jdbc.fetch_size ===== ===== hibernate.jdbc.fetch_size =====
-TBD+  * [[https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/5/html/performance_tuning_guide/sect-performance_tuning_guide-entity_beans-batching_database_operations|4.5.4. Batching Database Operations - Red Hat Customer Portal]] 
 +>  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 수이고(단,[[database:mysql|MySQL]]은 항상 전체 데이터를 한방에 읽는다고함. TBD
 + 
 +===== hibernate.jdbc.batch_size ===== 
 +  * [[java:hibernate:batch|Hibernate Batch/Bulk Insert/Update]] 
 +  * ''batch_size'' 는 update(insert,update,delete) 시에 묶어서 요청할 갯수이다. 
 +  * 이 때 sequence 기반으로 ID를 생성한다면, sequence 의 increment_size 도 동일하게 맞춰주는게 좋다. 
 +===== hibernate.query.in_clause_parameter_padding=true ===== 
 +  * Hibernate 5.2.18 이후 버전 ''hibernate.query.in_clause_parameter_padding=true'' 항상 ''true''로 둘 것. 
 +  * ''IN'' 절 쿼리에 대해서 2의 제곱단위로 쿼리를 생성한다. 
 +  * [[https://vladmihalcea.com/improve-statement-caching-efficiency-in-clause-parameter-padding/|How to improve statement caching efficiency with IN clause parameter padding - Vlad Mihalcea]] 
 +  * 위 옵션을 켜지 않으면, ''IN'' 절 쿼리가 ''QueryPlanCache''를 모두 점유해서 메모리가 부족해질수 있고, 메모리가 남아돌더라도 캐시를 모두 ''IN'' 절이 점유해버리므로 별로 좋지 못하다. 
 +  * 또한 RDBMS 의 경우 그 자체 execution plan cache 가 있는데, 이 옵션을 켜면 그에 대한 hit 율도 높아지게 된다. 
 +<note warning> 
 +[[database:mysql|MySQL]] 의 경우 in 쿼리의 ID 갯수가 너무 크면 index 를 타지 않고, 통계를 사용하는 경우가 있다. 
 + 
 +특히 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 안탐. 
 + 
 +참조 : [[https://jojoldu.tistory.com/565|MySQL IN절을 통한 성능 개선 방법]] 
 +</note> 
 +===== Hibernate Query Plan Cache ===== 
 +  * [[https://vladmihalcea.com/hibernate-query-plan-cache/|A beginner’s guide to the Hibernate JPQL and Native Query Plan Cache - Vlad Mihalcea]] 
 +  * ''hibernate.query.plan_cache_max_size'' 기본값은 ''2048'' 이다. 
 +  * 별문제 없으면 변경하지 말 것. 
 +===== autoCommit 을 꺼서 성능 향상시키기 ===== 
 +  * Connection Pool 의 ''auto commit=false''을 항상 켜고, Hibernate 에서 직접 ''auto commit=false'' 하는 것을 막아서 불필요한 ''setAutoCommit()'' 호출로 인한 성능 저하를 줄이기 
 + 
 +<note warning> 
 +아주 많은 Spring의 확장들이 auto commit=true를 가정하고 만들어져 있는 것으로 보인다. 
 + 
 +auto commit=false 이면서 Spring Data 사용시 제대로 Transaction이 안 걸려 있으면 오동작이 발생한다. 
 +모든 Repository 인터페이스와 Custom 구현에 ''@Transactional''을 붙여주어야 한다. 
 +</note> 
 + 
 +  * [[https://pkgonan.github.io/2019/01/hibrnate-autocommit-tuning|Hibernate setAutoCommit 최적화를 통한 성능 튜닝]] 
 +  * [[https://vladmihalcea.com/why-you-should-always-use-hibernate-connection-provider_disables_autocommit-for-resource-local-jpa-transactions/|Why you should always use hibernate.connection.provider_disables_autocommit for resource-local JPA transactions - Vlad Mihalcea]] 
 +  * 커넥션 풀 설정의 ''auto-commit: false''로 지정. 이걸 ''true''로 해버리면 트랜잭션이 안 먹음. 
 +  * ''hibernate.connection.provider_disables_autocommit: true''로 지정 : 커넥션 풀의 autocommit 을 무조건 따르겠다는 의미. ''5.2.10'' 이상 버전 
 +  * [[springframework:springboot:2|SpringBoot 2]] 부터는 커넥션 풀의 ''auto-commit'' 설정값에 따라 자동으로 ''hibernate.connection.provider_disables_autocommit: true'' 설정을 해준다.  
 +    * [[https://github.com/spring-projects/spring-boot/issues/9261|Consider disabling auto-commit when wiring connection pool configs and setting hibernate.connection.provider_disables_autocommit for resource-local transactions · Issue #9261 · spring-projects/spring-boot]] 
 +    * https://github.com/spring-projects/spring-boot/pull/9737 
 +    * ''HibernateJpaConfiguration.java'' <code java> 
 +if (!vendorProperties.containsKey(PROVIDER_DISABLES_AUTOCOMMIT)) {  
 +    configureProviderDisablesAutocommit(vendorProperties);  
 +
 + 
 +... 
 + 
 +if (isDataSourceAutoCommitDisabled() && !isJta()) {  
 +  vendorProperties.put(PROVIDER_DISABLES_AUTOCOMMIT, "true");  
 +
 +</code> 
 + 
 +> 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. 
  
 ===== Assert statement count  ===== ===== Assert statement count  =====
줄 39: 줄 114:
   * [[http://www.thoughts-on-java.org/tips-to-boost-your-hibernate-performance/|7 Tips to boost your Hibernate performance]]   * [[http://www.thoughts-on-java.org/tips-to-boost-your-hibernate-performance/|7 Tips to boost your Hibernate performance]]
   * [[https://www.youtube.com/watch?v=F5asq8ZG_1k|7 Tips to improve your Hibernate performance - YouTube]]   * [[https://www.youtube.com/watch?v=F5asq8ZG_1k|7 Tips to improve your Hibernate performance - YouTube]]
 +  * [[https://vladmihalcea.com/hibernate-performance-tuning-tips/|Hibernate performance tuning tips - Vlad Mihalcea]]
 +  * [[https://vladmihalcea.com/courses/high-performance-java-persistence-mach-2/|High-Performance Java Persistence – Mach 2 - Vlad Mihalcea]]
 +  * [[https://www.baeldung.com/hibernate-query-plan-cache|Hibernate Query Plan Cache | Baeldung]]
 +  * [[https://dzone.com/articles/best-performance-practices-for-hibernate-5-and-spr-1|Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 3) - DZone Java]]
 +  * [[https://dzone.com/articles/50-best-performance-practices-for-hibernate-5-amp|Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 1) - DZone Java]]
 +  * [[https://dzone.com/articles/best-performance-practices-for-hibernate-5-and-spr|Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 2) - DZone Java]]
 +  * [[https://dzone.com/articles/best-performance-practices-for-hibernate-5-and-spr-1|Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 3) - DZone Java]]
 +  * [[https://dzone.com/articles/best-performance-practices-for-hibernate-5-and-spr-2|Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 4) - DZone Java]]
 +  * [[https://dzone.com/articles/think-twice-whether-you-need-hibernate|Think Twice Whether You Need Hibernate - DZone Java]]
 +  * [[https://thorben-janssen.com/tips-to-boost-your-hibernate-performance/|Hibernate Performance Tuning Tips - 2022 Edition]]
java/hibernate/performance.1512047895.txt.gz · 마지막으로 수정됨: 2017/11/30 21:48 저자 kwon37xi