2012-09-26 11 views
6

Estoy usando Websphere Application Server 7 con buildin OpenJPA 1.2.3 y una base de datos Oracle. Tengo la siguiente entidad:Rendimiento La consulta OpenJPA (3000+ registros) es 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; 
     } 
    } 

Y el siguiente código para recuperar los contratos:

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

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

return contracts; 

Los contratos recuperados se pasan a un servicio web.

La ejecución de esta consulta en Oracle Developer toma alrededor de 0,35 segundos para 3608 registros. La llamada a query.getResultList() tarda alrededor de 4 segundos.

Con un registrador en el constuctor de la entidad, registra que hay alrededor de 10-20 entidades creadas con la misma marca de tiempo. Luego, 0,015 segundos hace algo más. Supongo que cosas de OpenJPA.

¿Hay alguna manera de acelerar OpenJPA? ¿O es la única solución de almacenamiento en caché?

+1

Le sugiero que use profiler. – user1516873

Respuesta

3

La creación de objetos puede tener su parte justa en el golpe de rendimiento. Mientras ejecuta su código en el servidor, no solo está consultando la base de datos, sino que también asigna memoria y crea un nuevo objeto Contract para cada fila. Un ciclo expansivo de recolección de basura o basura puede contar para períodos inactivos que usted observó.

Le sugiero que repase la documentación de OpenJPA sobre cómo procesar large results sets.

+1

openjpa.FetchBatchSize es realmente importante. En Oracle es (¿solía ser?) Solo 10. –

+0

He agregado el siguiente código: 'OpenJPAQuery kq = OpenJPAPersistence.cast (consulta); JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan(); fetch.setFetchBatchSize (100); fetch.setResultSetType (ResultSetType.SCROLL_INSENSITIVE); fetch.setFetchDirection (FetchDirection.FORWARD); fetch.setLRSSizeAlgorithm (LRSSizeAlgorithm.LAST); 'Cuando realizo una llamada al servicio web, devuelve un resultado en +/- 600ms. ¡Esto realmente rápido! Gracias por este gran consejo –

+0

También puede usar: 'query.setHint (" openjpa.FetchPlan.FetchBatchSize "," 100 "); query.setHint ("openjpa.FetchPlan.ResultSetType", "SCROLL_INSENSITIVE"); query.setHint ("openjpa.FetchPlan.LRSSizeAlgorithm", "LAST"); ' –

0

Le sugiero que descargue VisualVM y configure un perfil para los paquetes involucrados. VisualVM puede mostrar el tiempo empleado en diferentes métodos que sumarán hasta 0.35seg en su caso teóricamente. Podrá analizar la distribución del tiempo total entre su código, OpenJPA y el IO de la red. Esto te ayudará a identificar el cuello de botella.

+0

A menos que sea una sobrecarga de red. Lo cual probablemente sea –

+0

@Natan Cox Network se puede ver perfectamente, solo incluya java.io. * en los paquetes perfilados. La comunicación de la base de datos se verá como una especie de material de lectura. No recuerdo el nombre exacto del método. – jabal

Cuestiones relacionadas