BAEL-2456 Hibernate Query Plan Cache
This commit is contained in:
parent
ff01e708c9
commit
998e0a5b81
|
@ -74,9 +74,14 @@
|
||||||
<version>${hibernate.version}</version>
|
<version>${hibernate.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.dropwizard.metrics</groupId>
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
<artifactId>metrics-core</artifactId>
|
<artifactId>jmh-core</artifactId>
|
||||||
<version>${dropwizard-metrics.version}</version>
|
<version>${openjdk-jmh.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-generator-annprocess</artifactId>
|
||||||
|
<version>${openjdk-jmh.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -97,7 +102,7 @@
|
||||||
<h2database.version>1.4.196</h2database.version>
|
<h2database.version>1.4.196</h2database.version>
|
||||||
<assertj-core.version>3.8.0</assertj-core.version>
|
<assertj-core.version>3.8.0</assertj-core.version>
|
||||||
<jackson.version>2.9.7</jackson.version>
|
<jackson.version>2.9.7</jackson.version>
|
||||||
<dropwizard-metrics.version>4.0.5</dropwizard-metrics.version>
|
<openjdk-jmh.version>1.21</openjdk-jmh.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.baeldung.hibernate.queryplancache;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.HibernateUtil;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.jpa.QueryHints;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.Fork;
|
||||||
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Param;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
import org.openjdk.jmh.annotations.TearDown;
|
||||||
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
import org.openjdk.jmh.runner.RunnerException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class QueryPlanCacheBenchmark {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(QueryPlanCacheBenchmark.class);
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
public static class QueryPlanCacheBenchMarkState {
|
||||||
|
@Param({"1", "2", "3"})
|
||||||
|
public int planCacheSize;
|
||||||
|
|
||||||
|
public Session session;
|
||||||
|
|
||||||
|
@Setup
|
||||||
|
public void stateSetup() throws IOException {
|
||||||
|
LOGGER.info("State - Setup");
|
||||||
|
session = initSession(planCacheSize);
|
||||||
|
LOGGER.info("State - Setup Complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session initSession(int planCacheSize) throws IOException {
|
||||||
|
Properties properties = HibernateUtil.getProperties();
|
||||||
|
properties.put("hibernate.query.plan_cache_max_size", planCacheSize);
|
||||||
|
properties.put("hibernate.query.plan_parameter_metadata_max_size", planCacheSize);
|
||||||
|
SessionFactory sessionFactory = HibernateUtil.getSessionFactoryByProperties(properties);
|
||||||
|
return sessionFactory.openSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TearDown
|
||||||
|
public void tearDownState() {
|
||||||
|
LOGGER.info("State - Teardown");
|
||||||
|
SessionFactory sessionFactory = session.getSessionFactory();
|
||||||
|
session.close();
|
||||||
|
sessionFactory.close();
|
||||||
|
LOGGER.info("State - Teardown complete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
@Fork(1)
|
||||||
|
@Warmup(iterations = 2)
|
||||||
|
@Measurement(iterations = 5)
|
||||||
|
public void givenQueryPlanCacheSize_thenCompileQueries(QueryPlanCacheBenchMarkState state, Blackhole blackhole) {
|
||||||
|
|
||||||
|
Query query1 = findEmployeesByDepartmentNameQuery(state.session);
|
||||||
|
Query query2 = findEmployeesByDesignationQuery(state.session);
|
||||||
|
Query query3 = findDepartmentOfAnEmployeeQuery(state.session);
|
||||||
|
|
||||||
|
blackhole.consume(query1);
|
||||||
|
blackhole.consume(query2);
|
||||||
|
blackhole.consume(query3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Query findEmployeesByDepartmentNameQuery(Session session) {
|
||||||
|
return session.createQuery("SELECT e FROM DeptEmployee e " +
|
||||||
|
"JOIN e.department WHERE e.department.name = :deptName")
|
||||||
|
.setMaxResults(30)
|
||||||
|
.setHint(QueryHints.HINT_FETCH_SIZE, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Query findEmployeesByDesignationQuery(Session session) {
|
||||||
|
return session.createQuery("SELECT e FROM DeptEmployee e " +
|
||||||
|
"WHERE e.title = :designation")
|
||||||
|
.setHint(QueryHints.SPEC_HINT_TIMEOUT, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Query findDepartmentOfAnEmployeeQuery(Session session) {
|
||||||
|
return session.createQuery("SELECT e.department FROM DeptEmployee e " +
|
||||||
|
"JOIN e.department WHERE e.employeeNumber = :empId");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String... args) throws IOException, RunnerException {
|
||||||
|
//main-class to run the benchmark
|
||||||
|
org.openjdk.jmh.Main.main(args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,105 +0,0 @@
|
||||||
package com.baeldung.hibernate.queryplancache;
|
|
||||||
|
|
||||||
import com.baeldung.hibernate.HibernateUtil;
|
|
||||||
import com.codahale.metrics.Timer;
|
|
||||||
import com.codahale.metrics.UniformReservoir;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.SessionFactory;
|
|
||||||
import org.hibernate.jpa.QueryHints;
|
|
||||||
import org.hibernate.query.Query;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class QueryPlanCacheUnitTest {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(QueryPlanCacheUnitTest.class);
|
|
||||||
|
|
||||||
@Parameterized.Parameters
|
|
||||||
public static List<Integer[]> planCacheSize() {
|
|
||||||
List<Integer[]> planCacheSizes = new ArrayList<>();
|
|
||||||
|
|
||||||
planCacheSizes.add(new Integer[]{1});
|
|
||||||
planCacheSizes.add(new Integer[]{2});
|
|
||||||
planCacheSizes.add(new Integer[]{3});
|
|
||||||
|
|
||||||
|
|
||||||
return planCacheSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Timer timer = new Timer(new UniformReservoir(9900));
|
|
||||||
|
|
||||||
private int planCacheSize;
|
|
||||||
|
|
||||||
public QueryPlanCacheUnitTest(int planCacheSize) {
|
|
||||||
this.planCacheSize = planCacheSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void givenQueryPlanCacheSize_thenCompileQueries() throws IOException {
|
|
||||||
Session session = initSession();
|
|
||||||
|
|
||||||
//warm-up
|
|
||||||
for (int i = 0; i < 9900; i++) {
|
|
||||||
createFindEmployeesByDepartmentNameQuery(session);
|
|
||||||
createFindEmployeesByDesignationQuery(session);
|
|
||||||
createFindDepartmentOfAnEmployeeQuery(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 3300; i++) {
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
createFindEmployeesByDepartmentNameQuery(session);
|
|
||||||
timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
|
|
||||||
|
|
||||||
startTime = System.nanoTime();
|
|
||||||
createFindEmployeesByDesignationQuery(session);
|
|
||||||
timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
|
|
||||||
|
|
||||||
startTime = System.nanoTime();
|
|
||||||
createFindDepartmentOfAnEmployeeQuery(session);
|
|
||||||
timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("Query Plan Cache Size - {}, Time(Nanoseconds) - {}", planCacheSize, timer.getSnapshot().get95thPercentile());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Session initSession() throws IOException {
|
|
||||||
Properties properties = HibernateUtil.getProperties();
|
|
||||||
properties.put("hibernate.query.plan_cache_max_size", planCacheSize);
|
|
||||||
properties.put("hibernate.query.plan_parameter_metadata_max_size", planCacheSize);
|
|
||||||
SessionFactory sessionFactory = HibernateUtil.getSessionFactoryByProperties(properties);
|
|
||||||
return sessionFactory.openSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Query createFindEmployeesByDepartmentNameQuery(Session session) {
|
|
||||||
return session.createQuery("SELECT e FROM DeptEmployee e " +
|
|
||||||
"JOIN e.department WHERE e.department.name = :deptName")
|
|
||||||
.setMaxResults(30)
|
|
||||||
.setHint(QueryHints.HINT_FETCH_SIZE, 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Query createFindEmployeesByDesignationQuery(Session session) {
|
|
||||||
return session.createQuery("SELECT e FROM DeptEmployee e " +
|
|
||||||
"WHERE e.title = :designation")
|
|
||||||
.setHint(QueryHints.SPEC_HINT_TIMEOUT, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Query createFindDepartmentOfAnEmployeeQuery(Session session) {
|
|
||||||
return session.createQuery("SELECT e.department FROM DeptEmployee e " +
|
|
||||||
"JOIN e.department WHERE e.employeeNumber = :empId");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue