使用hibernate在DB中插入100000条记录

时间:2013-11-15 19:21:19

标签: hibernate sybase

我正在使用Hibernate在sybase数据库中输入100000条记录...但它花了一个多小时......已经使用了hibernate批处理仍然需要同时...有什么方法可以提高性能...我想要在不到10分钟的时间内保存100000条记录......但无法实现这一目标。

在配置文件中设置了hibernate_batch_size。

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

是否可以使用hibernate在DB中插入100000条记录。我可以在20秒内使用Ibatis在数据库中插入20000条记录,但是休眠需要几个小时才能完成

3 个答案:

答案 0 :(得分:1)

如果您在映射中使用id生成器,则Hibernate将静默禁用hibernate batch。更多信息here和hibernate文档第4章。

我会使用hibernate而不是对象来寻找Workjdbc。至少可以通过这种方式对性能进行比较。

您正在创建一个Customer对象,然后当您持久化它session.save()时,它可能会到达DB以获取该ID。然后将客户添加到Hibernate session(1级缓存)。

当你创建,持久化,添加到会话20个对象时,flush()执行实际的插入。然后清除缓存。这些引用设置为null并标记为集合。但是,根据您的heap分布和gc设置,这些实例可能已经提升到终身空间。即使不是,也会执行次要的gc。

一个优化可以在java代码中生成客户ID。另一个优化是使用多线程,我会选择两者。

在数据库外部生成ID以便按Customer保存连接的最简单方法是使用AtomicLong(必须根据customer中的ID列定义选择类型表)。如果批次不是一次性操作,则必须使用DB中的最高ID进行初始化:

然后使用批处理激活ExecutorCompletionService并在完成所有操作后提交(flushclear)。根据需要重复多次。

一个天真的例子:

select max(id) from custormer;

AtomicLong初始化为该值,然后使用incrementAndGet()(首先递增,然后返回更新后的值)。

使用AtomicLong可以使您的代码以多线程方式运行。

生成ID和多线程并行执行也适用于前面提到的jdbc discrete work

注意:并发执行可以利用多核环境,如果您的计算机是单核,则多线程不会获得太多收益。然后你可以使用一个简单的int来生成id,因为一切都是连续发生的。

答案 1 :(得分:1)

加载那么多行是DBA类型的作业,最好使用命令行工具/命令。我不熟悉sybase,但是会有一个命令直接从csv文件加载到表中。

Java / hibernate可能是最糟糕的工作工具 - 内存和CPU很重,并且没有增加任何价值。

答案 2 :(得分:0)

使用无状态会话(没有持久性上下文缓存): 这可以加快流程

Session session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
   Item item = new Item(...);
   session.save(item);
   if ( i % 100 == 0 ) {
     session.flush();
     session.clear(); 
   }
}
tx.commit();
session.close();

希望这有帮助