2012-09-26 14 views
6

Ich verwende Websphere Application Server 7 mit integriertem OpenJPA 1.2.3 und eine Oracle-Datenbank. Ich habe die folgende Einheit:Leistung OpenJPA-Abfrage (3000+ Datensätze) ist langsam

@NamedNativeQuery(name=Contract.GIVE_ALL_CONTRACTS, 
     query="SELECT number, name \n" + 
      "FROM contracts \n" + 
      "WHERE startdate <= ?1 \n" + 
      "AND enddate > ?1", 
      resultSetMapping = Contract.GIVE_ALL_CONTRACTS_MAPPING) 
    @SqlResultSetMapping(name = Contract.GIVE_ALL_CONTRACTS_MAPPING, 
     entities = { @EntityResult(entityClass = Contract.class, fields = { 
      @FieldResult(name = "number", column = "number"), 
      @FieldResult(name = "name", column = "name") 
     }) 
    }) 
    @Entity 
    public class Contract { 
     public static final String GIVE_ALL_CONTRACTS = "Contract.giveAllContracts"; 
     public static final String GIVE_ALL_CONTRACTS_MAPPING = "Contract.giveAllContractsMapping"; 

     @Id 
     private Integer number; 
     private String name; 

     public Integer getNumber() { 
     return number; 
     } 
     public String getName() { 
     return name; 
     } 
    } 

und den folgenden Code, um die Verträge zu erhalten:

Query query = entityManager.createNamedQuery(Contract.GIVE_ALL_CONTRACTS); 
query.setParameter(1, referenceDate); 

List contracts = query.getResultList(); 
entityManager.clear(); 

return contracts; 

Die abgerufenen Aufträge werden an einen Webservice übergeben.

Das Ausführen dieser Abfrage in Oracle-Entwickler dauert ca. 360 Sekunden für 3608 Datensätze. Der Aufruf von query.getResultList() dauert etwa 4 Sekunden.

Mit einem Logger im Konstruktor der Entität protokolliert er, dass etwa 10-20 Entitäten mit demselben Zeitstempel erstellt wurden. Dann 0,015 Sekunden macht es etwas anderes. Ich denke, OpenJPA Zeug.

Gibt es eine Möglichkeit, OpenJPA zu beschleunigen? Oder ist die einzige Lösung Caching?

+1

Ich empfehle Ihnen Profiler zu verwenden. – user1516873

Antwort

3

Die Objekterstellung kann ihren gerechten Anteil am Performance-Hit haben. Während Sie Ihren Code auf dem Server ausführen, fragen Sie nicht nur die Datenbank ab, sondern weisen auch Speicher zu und erstellen für jede Zeile ein neues Vertragsobjekt. Ein expandierender Heap- oder Speicherbereinigungszyklus kann für von Ihnen beobachtete Leerlaufperioden zählen.

Ich würde vorschlagen, dass Sie die OpenJPA-Dokumentation zur Verarbeitung von large results sets überfliegen.

+1

openjpa.FetchBatchSize ist wirklich wichtig. In Oracle ist es (früher?) Nur 10. –

+0

Ich habe den folgenden Code hinzugefügt: 'OpenJPAQuery kq = OpenJPAPersistence.cast (query); JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan(); fetch.setFetchBatchSize (100); fetch.setResultSetType (ResultSetType.SCROLL_INSENSITIVE); fetch.setFetchDirection (FetchDirection.FORWARD); fetch.setLRSSizeAlgorithm (LRSSizeAlgorithm.LAST); 'Wenn ich einen Aufruf an den Webservice mache, wird ein Ergebnis in +/- 600ms zurückgegeben. Das geht wirklich schnell! Danke für diesen tollen Tipp –

+0

Sie können auch verwenden: 'query.setHint (" openjpa.FetchPlan.FetchBatchSize "," 100 "); query.setHint ("openjpa.FetchPlan.ResultSetType", "SCROLL_INSENSITIVE"); query.setHint ("openjpa.FetchPlan.LRSSizeAlgorithm", "LAST"); ' –

0

Ich empfehle Ihnen, VisualVM herunterzuladen und ein Profiling für die beteiligten Pakete einzurichten. VisualVM kann die Zeit in verschiedenen Methoden anzeigen, die in Ihrem Fall theoretisch zu 0,35 Sekunden zusammenfasst. Sie können die Verteilung der Gesamtzeit zwischen Ihrem Code, OpenJPA und dem Netzwerk-IO analysieren. Dies wird Ihnen helfen, den Engpass zu identifizieren.

+0

Es sei denn, es ist Netzwerk-Overhead. Was es wahrscheinlich ist. –

+0

@Natan Cox Network kann perfekt gesehen werden, einfach java.io. * in die profilierten Pakete aufnehmen. Die Datenbankkommunikation wird als eine Art io.read angesehen, ich erinnere mich nicht an den genauen Methodennamen. – jabal

Verwandte Themen