同事在公司论坛里面发的,其实是我接手的一个项目中存在这个问题。
在使用Hibernate分页器时,习惯使用直接把查询语句、页数、分页大小,传给分页器,这样会默认使用last来获取总记录数,效率非常的低。
解决方法,很简单,就是用SQL来count查询条件获得总记录的Query,再给Hibernate分页器(本身就写好了的)。
这样就必须多写几行代码,就是因为自己懒,觉着效果都一样,就简单的写了。
数据量大了以后,就很明显的速度慢下来了。又全部重头改过,很是郁闷。
转载此文,以示提醒!
即使懒得研究Hibernate底层,也要注意它的效率问题。
我看到一些资料这样说,oracle的jdbc驱动是不支持服务器端的游标的,当你调用resultSet.last()时,jdbc驱动程序会把整个结果集的数据读到内存,然后在内存中进行结果集的遍历。
如果在做分页的时候,用这样的方式获取结果的总记录数:
rs.last();
int rowcount = rs.getRow();
在结果集很大的时候,这个性能是相当低下的,并且会用掉很多的内存。
这个问题是昨天在检查人才网的代码时发现的,随着数据增加,原来被掩盖的问题才开始暴露出来。我们用jprofiler对程序进行剖析的情况也间接的证明了上面的说法:1) 连续几次刷新工作列表后,虚拟机的内存被占满了,运行垃圾回收后内存又被释放出来。2) 从页面请求到完成响应,resultSet.last()方法的调用占去了cpu的绝大部分时间。
因为上面提到的分页方法是一种常用的方法,我建议大家考虑一下自己的代码是否存在这样的问题,这对办公系统的稳定运行可能是很重要的。
参考:
http://www.oracle.com/technology/global/cn/sample_code/tech/java/codesnippet/jdbc/rs/CountResult.html
提到了:
如果 ResultSet 非常大,则 resultset.last() 有可能是非常费时的操作,因为它将使用服务器端的更多资源。因此,除非确实需要可滚动结果集,应避免使用这种方法。
http://forum.springframework.org/showthread.php?t=50044&page=2
提到了:
Anyway, if it's a normal behaviour of the oracle driver to keep data in memory when using SCROLLABLE resultset
http://xiongbo.javaeye.com/blog/38481
对几种游标类型做了介绍,并给出了建议
posted on 2008-05-28 11:26
rox 阅读(4172)
评论(4) 编辑 收藏 所属分类:
hibernate