La fusión/persistencia de OpenJPA es muy lenta

Uso OpenJPA 2.2.0 en WebSphere Application Server 8 con MySQL 5.0 DB.

Tengo una lista de objetos que quiero fusionar en la base de datos.

es como:

for (Object ob : list) {
            Long start = Calendar.getInstance().getTimeInMillis();
            em = factory.createEntityManager();
            em.getTransaction().begin();

            em.merge(ob);

            em.getTransaction().commit();
            em.close();
            Long end = Calendar.getInstance().getTimeInMillis();
            Long diff = end - start;
            LOGGER.info("Time: " + diff);
        }

Cuando ejecuto este bucle, necesito entre 300 y 600 milisegundos para fusionar un objeto. Cuando elimino la línea "em.merge(ob);" entonces necesito "0" milisegundos para iterar sobre 1 objeto de lista.

Entonces mi pregunta es: ¿Qué puedo hacer para mejorar el tiempo para fusionar un objeto?

¡Gracias!

preguntado el 12 de junio de 12 a las 10:06

Active el inicio de sesión de SQL, vea qué solicitudes se generan y vea cuáles están tardando y por qué. -

1 Respuestas

Puede intentar iniciar la transacción antes de la iteración y luego confirmarla en una sola transacción. Entonces, básicamente, está creando un lote que se fusionaría/persistiría en la confirmación.

Además, puede limitar la cantidad de objetos en un lote que se procesarán a la vez y puede descargar explícitamente los cambios en la base de datos.

Aquí, está iniciando una transacción y comprometiéndola en cada iteración y también creando/cerrando el administrador de la entidad cada vez, afectará el rendimiento de numerosos datos.

Será algo como el siguiente código.

em = factory.createEntityManager();
em.getTransaction().begin();
int i = 0;

   for (Object ob : list) {
       Long start = Calendar.getInstance().getTimeInMillis();

       em.merge(ob);

       Long end = Calendar.getInstance().getTimeInMillis();
       Long diff = end - start;
       LOGGER.info("Time: " + diff);

       /*BATCH_SIZE is the number of entities 
            that will be persisted/merged at once */

       if(i%BATCH_SIZE == 0){    
           em.flush();
           em.clear(); 
       }

       i++;
   }

em.getTransaction().commit();
em.close();

Aquí, también puede revertir toda la transacción si alguno de los objetos no persiste/fusiona.

Respondido el 12 de junio de 12 a las 16:06

gracias, he intentado esto antes, pero cuantos más objetos tenga, más lenta será la fusión, tengo alrededor de 4000 objetos en mi lista: Veo

@veote Como ya mencioné, puede restringir la cantidad de entidades explícitamente. Se agregó lógica de lote al código donde puede especificar el tamaño de lote apropiado (por ejemplo, tome 100, luego los cambios en 100 entidades se reflejarán en la base de datos inmediatamente a la vez), consulte el código. - Nayan Wadekar

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.