2012-09-26 13 views
6

Utilizzo Websphere Application Server 7 con build OpenJPA 1.2.3 e un database Oracle. Ho la seguente entità:Prestazioni La query OpenJPA (3000+ record) è lenta

@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; 
     } 
    } 

E il seguente codice per recuperare i contratti:

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

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

return contracts; 

I contratti recuperati vengono passati ad un webservice.

L'esecuzione di questa query nello sviluppatore Oracle richiede circa 0,35 secondi per i record 3608. La chiamata a query.getResultList() richiede circa 4 secondi.

Con un logger nel constuctor dell'entità, registra che ci sono circa 10-20 entità create con lo stesso timestamp. Quindi 0,015 secondi fa qualcos'altro. Immagino roba OpenJPA.

C'è un modo per velocizzare OpenJPA? O è l'unica soluzione di memorizzazione nella cache?

+1

Ti suggerisco di usare profiler. – user1516873

risposta

3

La creazione di oggetti può avere la sua giusta parte nel colpo di prestazione. Durante l'esecuzione del codice nel server, non stai solo interrogando il database ma anche allochi la memoria e crei un nuovo oggetto Contratto per ogni riga. Un ciclo di espansione o di raccolta dei dati inutili può contare per i periodi di inattività che hai osservato.

Ti suggerisco di sfogliare la documentazione di OpenJPA su come elaborare large results sets.

+1

openjpa.FetchBatchSize è molto importante. In Oracle è (usato per essere?) Solo 10. –

+0

Ho aggiunto il seguente codice: '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); 'Quando faccio una chiamata al servizio web restituisce un risultato in +/- 600 ms. Questo molto veloce! Grazie per questo ottimo suggerimento –

+0

Puoi anche utilizzare: 'query.setHint (" openjpa.FetchPlan.FetchBatchSize "," 100 "); query.setHint ("openjpa.FetchPlan.ResultSetType", "SCROLL_INSENSITIVE"); query.setHint ("openjpa.FetchPlan.LRSSizeAlgorithm", "LAST"); ' –

0

Ti suggerisco di scaricare VisualVM e impostare una profilazione per i pacchetti coinvolti. VisualVM può mostrare il tempo trascorso in diversi metodi che riassumono fino a 0,35 secondi nel tuo caso teoricamente. Sarai in grado di analizzare la distribuzione del tempo totale tra il tuo codice, OpenJPA e la rete IO. Questo ti aiuterà a identificare il collo di bottiglia.

+0

A meno che non sia l'overhead di rete. Quale probabilmente è. –

+0

@Natan Cox Network può essere visto perfettamente, basta includere java.io. * nei pacchetti profilati. La comunicazione tra database sarà vista come una sorta di roba io.read o così, non ricordo il nome esatto del metodo. – jabal

Problemi correlati