6

我有一个 ~6GB 的文本文件,我需要对其进行解析并在以后保留。通过“解析”,我正在从文件中读取一行(通常为 2000 个字符),从该行创建一个 Car 对象,然后我将其持久化。

我正在使用生产者消费者模式来解析和持久化,并想知道一次持久化一个对象或一次提交 1000 个(或任何其他数量)是否有任何区别(出于性能原因)?

目前,坚持一切(300 万行)需要我 2 小时以上的时间,而且对我来说似乎时间太多(或者我可能错了)。

目前我正在这样做:

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() 应该是什么?此外,会话的打开/关闭是否被认为是昂贵的?

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

1 回答 1

5

传统上,hibernate 不能很好地处理批量插入。有一些方法可以将其优化到一定程度。

API Docs中的这个例子为例,

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 内。这里的代码可能看起来有点复杂,但非常有效。

于 2012-04-23T02:51:46.963 回答