2016-10-26 2 views
1

Ich bin vor Performance-Probleme der Ausführung Standard-Feder-data-JPA findAll Abfragen mit @NamedEntityGraphHibernate QueryTranslatorImpl HQL AST Parsing Leistung

Wenn ich die Protokolle untersuchen, habe ich die folgenden Aussagen sehen:

2016-10-26 09:46:25,681 DEBUG [http-nio-8080-exec-1] CriteriaQueryImpl: Rendered criteria query -> select generatedAlias0 from Patient as generatedAlias0 order by generatedAlias0.id asc 
2016-10-26 09:46:25,681 DEBUG [http-nio-8080-exec-1] CriteriaQueryImpl: Rendered criteria query -> select count(generatedAlias0) from Patient as generatedAlias0 
2016-10-26 09:46:25,681 DEBUG [http-nio-8080-exec-1] SQL: select count(patient0_.id) as col_0_0_ from patient patient0_ 
2016-10-26 09:46:25,682 DEBUG [http-nio-8080-exec-1] Loader: Result row: 
2016-10-26 09:46:25,682 DEBUG [http-nio-8080-exec-1] ConcurrentStatisticsImpl: HHH000117: HQL: select count(generatedAlias0) from Patient as generatedAlias0, time: 0ms, rows: 1 
2016-10-26 09:46:25,682 DEBUG [http-nio-8080-exec-1] QueryTranslatorImpl: parse() - HQL: select generatedAlias0 from com.fluidda.broncholab.domain.Patient as generatedAlias0 order by generatedAlias0.id asc 
2016-10-26 09:46:27,340 DEBUG [http-nio-8080-exec-1] QueryTranslatorImpl: --- HQL AST --- 
\-[QUERY] Node: 'query' 
    +-[SELECT_FROM] Node: 'SELECT_FROM' 
    | +-[FROM] Node: 'from' 
    | | \-[RANGE] Node: 'RANGE' 
    | |  +-[DOT] Node: '.' 
    | |  | +-[DOT] Node: '.' 
    | |  | | +-[DOT] Node: '.' 
    | |  | | | +-[DOT] Node: '.' 
    | |  | | | | +-[IDENT] Node: 'com' 
    | |  | | | | \-[IDENT] Node: 'fluidda' 
    | |  | | | \-[IDENT] Node: 'broncholab' 
    | |  | | \-[IDENT] Node: 'domain' 
    | |  | \-[IDENT] Node: 'Patient' 
    | |  \-[ALIAS] Node: 'generatedAlias0' 
    | \-[SELECT] Node: 'select' 
    |  \-[IDENT] Node: 'generatedAlias0' 
    \-[ORDER] Node: 'order' 
     +-[DOT] Node: '.' 
     | +-[IDENT] Node: 'generatedAlias0' 
     | \-[IDENT] Node: 'id' 
     \-[ASCENDING] Node: 'asc' 

2016-10-26 09:46:27,340 DEBUG [http-nio-8080-exec-1] ErrorCounter: throwQueryException() : no errors 
2016-10-26 09:46:27,340 DEBUG [http-nio-8080-exec-1] HqlSqlBaseWalker: select << begin [level=1, statement=select] 
2016-10-26 09:46:27,341 DEBUG [http-nio-8080-exec-1] FromElement: FromClause{level=1} : com.fluidda.broncholab.domain.Patient (generatedAlias0) -> patient0_ 

Es ist eine große Lücke zwischen 2 QueryTranslatorImpl Log-Aussagen: fast 2 Sekunden ?!

Wenn im Quelltext suchen, ich sehe nichts besonderes (hibernate-core-4.3.11.Final)

private HqlParser parse(boolean filter) throws TokenStreamException, RecognitionException { 
    // Parse the query string into an HQL AST. 
    final HqlParser parser = HqlParser.getInstance(hql); 
    parser.setFilter(filter); 

    LOG.debugf("parse() - HQL: %s", hql); 
    parser.statement(); 

    final AST hqlAst = parser.getAST(); 

    final NodeTraverser walker = new NodeTraverser(new JavaConstantConverter()); 
    walker.traverseDepthFirst(hqlAst); 

    showHqlAst(hqlAst); 

    parser.getParseErrorHandler().throwQueryException(); 
    return parser; 
} 

Was ist das Problem hier? Es ist eine sehr einfache HQL, warum dauert es so lange?

Ist es möglich, diese HQL AST-Analyse zu cachen?

Antwort

3

Die HQL-Abfragepläne werden aus Leistungsgründen im Cache gespeichert. Sie können die Abfrage-Plan-Cache-Steuerung unter Verwendung der folgenden two configuration properties:

  • hibernate.query.plan_cache_max_size = 2048 (Standardwert)
  • hibernate.query.plan_parameter_metadata_max_size = 128 (Standardwert)

Versuchen Sie, den hibernate.query.plan_cache_max_size Wert auf einen Wert erhöht wird, die ist passend für Ihre Datenzugriffsmuster.

In meinem Buch, High-Performance Java Persistence, habe ich erläutert, warum Sie diese beiden Werte richtig konfigurieren sollten, da andernfalls das Analysieren der HQL-Abfragen zu einem Leistungsengpass werden könnte.

+0

Danke Vlad. Bedeutet das, dass das Ausführen einer HQL-Abfrage beim ersten Mal immer langsam ist? –

+1

Dies ist mit jeder Datenbankabfrage identisch. Wenn Sie eine Abfrage zum ersten Mal ausführen, muss die Datenbank einen Ausführungsplan generieren. Einige DBs können den Plan zwischenspeichern (z. B. Oracle, SQL Server), sodass die erste Ausführung langsamer ist. Dasselbe gilt für HQL-Abfragen. Wenn sie zum ersten Mal ausgeführt werden, werden sie langsamer sein. Aber wenn Sie den HQL-Plan richtig zwischenspeichern, sind alle anderen Ausführungen schnell. –

+0

Ich habe es vorher nicht erwähnt, aber ich sehe keine HQL-Parsing-Zeit von 2 Sekunden die ganze Zeit. Meistens dauert es nur etwa 30 ms, um den HQL zu analysieren (natürlich für dieselbe Abfrage). Irgendeine Idee, warum Parsing-Zeit nicht konsistent ist? –