OpenJPA合并/持久化非常缓慢。

3

我使用OpenJPA 2.2.0在WebSphere应用服务器8上,与MySQL 5.0数据库一起使用。

我有一个对象列表,我想将其合并到数据库中。

就像这样:

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

当我运行这个循环时,我需要大约300-600毫秒来合并一个对象。当我删除"em.merge(ob);"这一行时,我需要"0"毫秒来迭代1个列表对象。
所以我的问题是:我该怎么做才能提高合并一个对象的时间?
谢谢!

2
打开SQL日志记录,查看生成的请求以及哪些请求花费了时间以及原因。 - JB Nizet
1个回答

7
您可以尝试在迭代之前启动事务,然后在单个事务中执行提交。因此,您正在创建一个批处理,该批处理将在提交时合并/持久化。

另外,您可以限制每次处理的对象数,并明确将更改刷新到数据库。

在这里,您在每次迭代中初始化事务并提交它,还创建/关闭实体管理器,这将影响大量数据的性能。

代码如下所示:

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();

在这里,如果任何对象无法持久化/合并,您还可以回滚整个事务。


谢谢,我之前尝试过这个方法,但是我的列表里有大约4000个对象,合并的速度会越来越慢。 - veote
@veote 正如我之前提到的,您可以明确限制实体的数量。在代码中添加了批处理逻辑,您可以指定适当的批处理大小(例如取100个),然后一次性将100个实体的更改立即反映在数据库中。请参考代码。 - Nayan Wadekar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接