我正在使用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条记录,但是休眠需要几个小时才能完成
答案 0 :(得分:1)
如果您在映射中使用id生成器,则Hibernate将静默禁用hibernate batch
。更多信息here和hibernate文档第4章。
我会使用hibernate而不是对象来寻找Work
和jdbc
。至少可以通过这种方式对性能进行比较。
您正在创建一个Customer
对象,然后当您持久化它session.save()
时,它可能会到达DB以获取该ID。然后将客户添加到Hibernate session
(1级缓存)。
当你创建,持久化,添加到会话20个对象时,flush()
执行实际的插入。然后清除缓存。这些引用设置为null并标记为集合。但是,根据您的heap
分布和gc设置,这些实例可能已经提升到终身空间。即使不是,也会执行次要的gc。
一个优化可以在java代码中生成客户ID。另一个优化是使用多线程,我会选择两者。
在数据库外部生成ID以便按Customer
保存连接的最简单方法是使用AtomicLong
(必须根据customer
中的ID列定义选择类型表)。如果批次不是一次性操作,则必须使用DB中的最高ID进行初始化:
然后使用批处理激活ExecutorCompletionService
并在完成所有操作后提交(flush
和clear
)。根据需要重复多次。
一个天真的例子:
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();
希望这有帮助