HHH-14632 - Call statistics.queryPlanCacheHit and statistics.queryPlanCacheMiss for FilterQueryPlan and NativeSQLQueryPlan
This commit is contained in:
parent
7570f39d10
commit
cea044ec69
|
@ -200,6 +200,8 @@ public class QueryPlanCache implements Serializable {
|
||||||
Map<String,Filter> enabledFilters) throws QueryException, MappingException {
|
Map<String,Filter> enabledFilters) throws QueryException, MappingException {
|
||||||
final FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters );
|
final FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters );
|
||||||
FilterQueryPlan value = (FilterQueryPlan) queryPlanCache.get( key );
|
FilterQueryPlan value = (FilterQueryPlan) queryPlanCache.get( key );
|
||||||
|
final StatisticsImplementor statistics = factory.getStatistics();
|
||||||
|
boolean stats = statistics.isStatisticsEnabled();
|
||||||
if ( value == null ) {
|
if ( value == null ) {
|
||||||
LOG.tracev(
|
LOG.tracev(
|
||||||
"Unable to locate collection-filter query plan in cache; generating ({0} : {1} )",
|
"Unable to locate collection-filter query plan in cache; generating ({0} : {1} )",
|
||||||
|
@ -207,10 +209,17 @@ public class QueryPlanCache implements Serializable {
|
||||||
filterString
|
filterString
|
||||||
);
|
);
|
||||||
value = new FilterQueryPlan( filterString, collectionRole, shallow, enabledFilters,factory );
|
value = new FilterQueryPlan( filterString, collectionRole, shallow, enabledFilters,factory );
|
||||||
|
if ( stats ) {
|
||||||
|
statistics.queryPlanCacheMiss( key.query );
|
||||||
|
}
|
||||||
queryPlanCache.putIfAbsent( key, value );
|
queryPlanCache.putIfAbsent( key, value );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.tracev( "Located collection-filter query plan in cache ({0} : {1})", collectionRole, filterString );
|
LOG.tracev( "Located collection-filter query plan in cache ({0} : {1})", collectionRole, filterString );
|
||||||
|
|
||||||
|
if ( stats ) {
|
||||||
|
statistics.queryPlanCacheHit( key.query );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -228,13 +237,22 @@ public class QueryPlanCache implements Serializable {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public NativeSQLQueryPlan getNativeSQLQueryPlan(final NativeSQLQuerySpecification spec) {
|
public NativeSQLQueryPlan getNativeSQLQueryPlan(final NativeSQLQuerySpecification spec) {
|
||||||
NativeSQLQueryPlan value = (NativeSQLQueryPlan) queryPlanCache.get( spec );
|
NativeSQLQueryPlan value = (NativeSQLQueryPlan) queryPlanCache.get( spec );
|
||||||
|
final StatisticsImplementor statistics = factory.getStatistics();
|
||||||
|
boolean stats = statistics.isStatisticsEnabled();
|
||||||
if ( value == null ) {
|
if ( value == null ) {
|
||||||
LOG.tracev( "Unable to locate native-sql query plan in cache; generating ({0})", spec.getQueryString() );
|
LOG.tracev( "Unable to locate native-sql query plan in cache; generating ({0})", spec.getQueryString() );
|
||||||
value = nativeQueryInterpreter.createQueryPlan( spec, factory );
|
value = nativeQueryInterpreter.createQueryPlan( spec, factory );
|
||||||
|
if ( stats ) {
|
||||||
|
statistics.queryPlanCacheMiss( spec.getQueryString() );
|
||||||
|
}
|
||||||
queryPlanCache.putIfAbsent( spec, value );
|
queryPlanCache.putIfAbsent( spec, value );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.tracev( "Located native-sql query plan in cache ({0})", spec.getQueryString() );
|
LOG.tracev( "Located native-sql query plan in cache ({0})", spec.getQueryString() );
|
||||||
|
|
||||||
|
if ( stats ) {
|
||||||
|
statistics.queryPlanCacheHit( spec.getQueryString() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,10 @@ public class QueryStatisticsImpl implements QueryStatistics {
|
||||||
planCacheHitCount.increment();
|
planCacheHitCount.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void incrementPlanCacheMissCount() {
|
||||||
|
planCacheMissCount.increment();
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "QueryStatistics"
|
return "QueryStatistics"
|
||||||
+ "[query=" + query
|
+ "[query=" + query
|
||||||
|
|
|
@ -805,11 +805,20 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void queryPlanCacheHit(String hql) {
|
public void queryPlanCacheHit(String query) {
|
||||||
queryPlanCacheHitCount.increment();
|
queryPlanCacheHitCount.increment();
|
||||||
|
|
||||||
if ( hql != null ) {
|
if ( query != null ) {
|
||||||
getQueryStatistics( hql ).incrementPlanCacheHitCount();
|
getQueryStatistics( query ).incrementPlanCacheHitCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void queryPlanCacheMiss(String query) {
|
||||||
|
queryPlanCacheMissCount.increment();
|
||||||
|
|
||||||
|
if ( query != null ) {
|
||||||
|
getQueryStatistics( query ).incrementPlanCacheMissCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,9 +251,18 @@ public interface StatisticsImplementor extends Statistics, Service {
|
||||||
/**
|
/**
|
||||||
* Callback indicating a get from the query plan cache resulted in a hit.
|
* Callback indicating a get from the query plan cache resulted in a hit.
|
||||||
*
|
*
|
||||||
* @param hql The query
|
* @param query The query
|
||||||
*/
|
*/
|
||||||
default void queryPlanCacheHit(String hql) {
|
default void queryPlanCacheHit(String query) {
|
||||||
|
//For backward compatibility
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback indicating a get from the query plan cache resulted in a miss.
|
||||||
|
*
|
||||||
|
* @param query The query
|
||||||
|
*/
|
||||||
|
default void queryPlanCacheMiss(String query) {
|
||||||
//For backward compatibility
|
//For backward compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.LockModeType;
|
import javax.persistence.LockModeType;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Tuple;
|
import javax.persistence.Tuple;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
|
@ -150,7 +151,7 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
||||||
|
|
||||||
assertEquals( 5, employees.size() );
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
//The miss count is still 1, as no we got the query plan from the cache
|
//The miss count is still 1, as now we got the query plan from the cache
|
||||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
//And the cache hit count increases.
|
//And the cache hit count increases.
|
||||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
@ -164,7 +165,55 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
||||||
|
|
||||||
assertEquals( 5, employees.size() );
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
//The miss count is still 1, as no we got the query plan from the cache
|
//The miss count is still 1, as now we got the query plan from the cache
|
||||||
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
|
//And the cache hit count increases.
|
||||||
|
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-14632" )
|
||||||
|
public void testCreateNativeQueryHitCount() {
|
||||||
|
statistics.clear();
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
|
||||||
|
List<Employee> employees = entityManager.createNativeQuery(
|
||||||
|
"select * from employee e", Employee.class )
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
|
//First time, we get a cache miss, so the query is compiled
|
||||||
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
|
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||||
|
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
|
||||||
|
List<Employee> employees = entityManager.createNativeQuery(
|
||||||
|
"select * from employee e", Employee.class )
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
|
//The miss count is still 1, as now we got the query plan from the cache
|
||||||
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
|
//And the cache hit count increases.
|
||||||
|
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
|
||||||
|
List<Employee> employees = entityManager.createNativeQuery(
|
||||||
|
"select * from employee e", Employee.class )
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
|
//The miss count is still 1, as now we got the query plan from the cache
|
||||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
//And the cache hit count increases.
|
//And the cache hit count increases.
|
||||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
@ -232,7 +281,7 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
||||||
|
|
||||||
assertEquals( 5, employees.size() );
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
//The miss count is still 1, as no we got the query plan from the cache
|
//The miss count is still 1, as now we got the query plan from the cache
|
||||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
//And the cache hit count increases.
|
//And the cache hit count increases.
|
||||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
@ -246,7 +295,7 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
||||||
|
|
||||||
assertEquals( 5, employees.size() );
|
assertEquals( 5, employees.size() );
|
||||||
|
|
||||||
//The miss count is still 1, as no we got the query plan from the cache
|
//The miss count is still 1, as now we got the query plan from the cache
|
||||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||||
//And the cache hit count increases.
|
//And the cache hit count increases.
|
||||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||||
|
@ -292,6 +341,7 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "Employee")
|
@Entity(name = "Employee")
|
||||||
|
@Table(name = "employee")
|
||||||
@NamedQuery(
|
@NamedQuery(
|
||||||
name = "find_employee_by_name",
|
name = "find_employee_by_name",
|
||||||
query = "select e from Employee e where e.name = :name"
|
query = "select e from Employee e where e.name = :name"
|
||||||
|
|
Loading…
Reference in New Issue