Hibernate性能问题,逐个持久化还是批量持久化?

6
我有一个大约6GB的文本文件需要解析和持久化。所谓“解析”,就是读取文件中的一行(通常为2000个字符),从该行创建一个汽车对象,然后将其持久化。我使用生产者消费者模式来解析和持久化,并且想知道一次只持久化一个对象还是1000个(或其他任何数量)是否会对性能产生影响?
目前,我需要花费超过2小时才能完成所有持久化操作(300万行),这看起来对我来说太长了(或者我可能错了)。
目前我的做法如下:
public void persistCar(Car car) throws Exception
{
    try
    {
        carDAO.beginTransaction();  //get hibernate session...

        //do all save here.

        carDAO.commitTransaction(); // commit the session

    }catch(Exception e)
    {
        carDAO.rollback();
        e.printStackTrace(); 
    }
    finally
    {
        carDAO.close();
    }
}

在我进行任何设计更改之前,我想知道这个设计是否更好(或者不好),如果更好,那么cars.size()应该是多少?另外,开/关session是否被认为是昂贵的操作?
public void persistCars(List<Car> cars) throws Exception
{
    try
    {
        carDAO.beginTransaction();  //get hibernate session...
        for (Car car : cars)    
        //do all save here.

        carDAO.commitTransaction(); // commit the session

    }catch(Exception e)
    {
        carDAO.rollback();
        e.printStackTrace(); 
    }
    finally
    {
        carDAO.close();
    }
}
1个回答

5
传统上,Hibernate 与批量插入不太兼容。有一些方法可以在某种程度上进行优化。
API 文档中的示例为例:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    session.save(customer);
    if ( i % 20 == 0 ) { //20, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

在上面的例子中,插入20个条目后会刷新会话,这将使操作变得更快。
这里有一篇有趣的文章讨论了同样的内容。
我们已经成功地实现了使用存储过程进行批量插入的替代方法。在这种情况下,您将把参数作为“|”分隔的列表传递给SP,并将插入脚本编写到SP中。在这里,代码可能看起来有点复杂,但非常有效。

我会尝试这段代码以提高性能,并回复这个答案。谢谢! - adhg

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