现在的位置: 首页 > 综合 > 正文

hibernate的批量处理

2017年12月27日 ⁄ 综合 ⁄ 共 2412字 ⁄ 字号 评论关闭

Hibernate插入操作的机制:Hibernate要对它内部缓存进行维护,当我们执行插入操作时,就会把要操作的对象全部放到自身的内部缓存来进行管理。 
Hibernate的缓存:Hibernate有内部缓存与二级缓存。
对于二级缓存,我们可以对它的大小进行相关配置,
对于一级缓存,Hibernate就采取了“放任自流”的态度了,对它的容量并没有限制。
我们每次保存的东西都会保存在Session缓存中,这就是Hibernate的一级缓存,如果我们一直循环执行save等操作,缓存里东西会越来越多,速度也就越来越慢,服务器一直在循环处理,自然也会增加负载。
hibernate.jdbc.batch_size:指定每次提交SQL的数量

链接:http://youngflying.com/2012/09/14/hibernate-batch-processing/

链接:http://javaligang.blog.51cto.com/5026500/910675

链接:http://www.blogjava.net/weibogao/archive/2006/12/27/90245.html
总结下来有三种来处理以解决性能问题:
1:绕过Hibernate API ,直接通过 JDBC API 来做,这个方法性能上是比较好的。也是最快的.
2:运用存储过程。
3:还是用Hibernate API 来进行常规的批量处理,我们可以在查找出一定的量的时候,及时的将这些数据做完操作就删掉,session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。一般为30-60左右,但效果仍然不理想.

---批量插入优化

1、仍旧用Hibernate API来进行批处理,但在一定的量的时候,及时的清除缓存。

1)设置hibernate.jdbc.batch_size参数
<hibernate-configuration>
	<session-factory>
		.........
		<property name="hibernate.jdbc.batch_size">50</property>
		.........
	<session-factory>
<hibernate-configuration>

2)程序及时清除缓存,即每插入一定量的数据后及时把它们从内部缓存中清除掉,释放占用的内存。 Session实现了异步write-behind,它允许Hibernate显式地写操作的批处理。
// 每处理50条清空缓存
session.save(myObject);
if (i/50 == 0) {
	session.flush();
	session.clear();
}

// 在我的项目中写法如下:
if (i/50 == 0) {
	this.getHibernateTemplate().flush();
	this.getHibernateTemplate().clear();
}

2、通过JDBC API来做批量插入,绕过Hibernate API。这个方法性能上是最好的,也是最快的

	String insertSql = "insert into user(name,address) values(?,?)";
	Session session = getHibernateTemplate().getSessionFactory().openSession();
	Connection conn = session.connection();
	PrepareStatement stmt = conn.prepareStatement(insertSql);

	// 方式1:自动提交
	conn.setAutoCommit(true);
	for(int i = 0; i++; i<10000) {
		stmt.setString(1, "testName");
		stmt.setString(2, "testAddress");
		stmt.execute();
	}

	// 方式2:批量提交
	conn.setAutoCommit(false);
	for(int i = 0; i++; i<10000) {
		stmt.setString(1, "testName");
		stmt.setString(2, "testAddress");
		stmt.addBatch();
		if (i % 100 == 0) {
			stmt.executeBatch();
			conn.commit();
		}
	}
	stmt.executeBatch();
	conn.commit();

	// 关闭session
	session.close();

3.总结:
经测试:
1)若直接使用Hibernate,处理同样数据的时间会递增,甚至成倍增加,而且在测试过程中CPU使用率一直在70%上下。
2)若在使用Hibernate中每save一次都清空缓存的话,虽然时间不会递增,但处理速度很慢。在本例中采用每50个清空一次缓存较为合适,实际应用视情况而定。 一定量的时候清空缓存,虽然速度上没有提升,但会比较稳定,不会随着时间陡增,而且测试中CPU使用率也维持在20%上下,可以挽救一点性能损失,使系统相对稳定。
3)若使用JDBC API,不论auto commit方式还是batch方式,相比Hibernate在性能上都有近10倍的提升。不过在数据量较大的时候,推荐使用batch方式。

--批量更新与删除优化
Hibernate2中,对于批量更新/删除操作,都是先将符合要求的数据查出来,然后再做更新/删除操作。这样一来会占用大量内存,而且海量数据处理的时候性能很低。
而Hibernate3对批量更新/删除提供了支持,能够直接执行批量更新或批量删除语句,无需把被更新或删除的对象先加载到内存中,类似于JDBC的批量更新/删除操作。
不过对于循环处理数据更新和删除场景,建议还是使用JDBC,方法同上:批量插入的方法2。

抱歉!评论已关闭.