HHH-8977 Guess reasonable size for ArrayList and IdentitySet for Query

perform

Conflicts:
	hibernate-core/src/main/java/org/hibernate/engine/query/spi/HQLQueryPlan.java
This commit is contained in:
Sanne Grinovero 2014-02-18 15:03:10 -05:00 committed by Brett Meyer
parent 8e5e8d1b14
commit ec5987278d
1 changed files with 47 additions and 8 deletions

View File

@ -32,8 +32,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.ScrollableResults; import org.hibernate.ScrollableResults;
@ -53,6 +51,7 @@ import org.hibernate.internal.util.collections.EmptyIterator;
import org.hibernate.internal.util.collections.IdentitySet; import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.internal.util.collections.JoinedIterator; import org.hibernate.internal.util.collections.JoinedIterator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/** /**
* Defines a query execution plan for an HQL query (or filter). * Defines a query execution plan for an HQL query (or filter).
@ -172,10 +171,13 @@ public class HQLQueryPlan implements Serializable {
LOG.tracev( "Find: {0}", getSourceQuery() ); LOG.tracev( "Find: {0}", getSourceQuery() );
queryParameters.traceParameters( session.getFactory() ); queryParameters.traceParameters( session.getFactory() );
} }
boolean hasLimit = queryParameters.getRowSelection() != null &&
queryParameters.getRowSelection().definesLimits(); final RowSelection rowSelection = queryParameters.getRowSelection();
boolean needsLimit = hasLimit && translators.length > 1; final boolean hasLimit = rowSelection != null
QueryParameters queryParametersToUse; && rowSelection.definesLimits();
final boolean needsLimit = hasLimit && translators.length > 1;
final QueryParameters queryParametersToUse;
if ( needsLimit ) { if ( needsLimit ) {
LOG.needsLimit(); LOG.needsLimit();
RowSelection selection = new RowSelection(); RowSelection selection = new RowSelection();
@ -187,8 +189,9 @@ public class HQLQueryPlan implements Serializable {
queryParametersToUse = queryParameters; queryParametersToUse = queryParameters;
} }
List combinedResults = new ArrayList(); final int guessedResultSize = guessResultSize( rowSelection );
IdentitySet distinction = new IdentitySet(); final List combinedResults = new ArrayList( guessedResultSize );
final IdentitySet distinction = new IdentitySet( guessedResultSize );
int includedCount = -1; int includedCount = -1;
translator_loop: translator_loop:
for ( QueryTranslator translator : translators ) { for ( QueryTranslator translator : translators ) {
@ -223,6 +226,42 @@ public class HQLQueryPlan implements Serializable {
return combinedResults; return combinedResults;
} }
/**
* If we're able to guess a likely size of the results we can optimize allocation
* of our datastructures.
* Essentially if we detect the user is not using pagination, we attempt to use the FetchSize
* as a reasonable hint. If fetch size is not being set either, it is reasonable to expect
* that we're going to have a single hit. In such a case it would be tempting to return a constant
* of value one, but that's dangerous as it doesn't scale up appropriately for example
* with an ArrayList if the guess is wrong.
*
* @param rowSelection
* @return a reasonable size to use for allocation
*/
private final int guessResultSize(RowSelection rowSelection) {
if ( rowSelection != null ) {
final int maxReasonableAllocation = rowSelection.getFetchSize() != null ? rowSelection.getFetchSize().intValue() : 100;
if ( rowSelection.getMaxRows() != null && rowSelection.getMaxRows().intValue() > 0 ) {
return Math.min( maxReasonableAllocation, rowSelection.getMaxRows().intValue() );
}
else if ( rowSelection.getFetchSize() != null && rowSelection.getFetchSize().intValue() > 0 ) {
return rowSelection.getFetchSize().intValue();
}
}
return 7;//magic number guessed as a reasonable default.
}
/**
* Coordinates the efforts to perform an iterate across all the included query translators.
*
* @param queryParameters The query parameters
* @param session The session
*
* @return The query result iterator
*
* @throws HibernateException Indicates a problem performing the query
*/
@SuppressWarnings("unchecked")
public Iterator performIterate( public Iterator performIterate(
QueryParameters queryParameters, QueryParameters queryParameters,
EventSource session) throws HibernateException { EventSource session) throws HibernateException {