最近开发hr系统,需要用HQL语句导出excel(1500行*100列),一开始5-6行/s,执行至500行时3行/s,到1000行1行/1s。
一开始认为是jxl写入速度越来越慢,去掉写入excel,依旧是慢。
然后怀疑到hibernate的查询上,每一行都涉及到6,7条hql语句。
但不明白为什么查询会减速执行,而不是匀速?
[b]问题补充:[/b]
可以排除数据库执行sql语句的因素。
hibernate会不会出现类似问题。
[b]问题补充:[/b]
数据库为Mysql,c3p0连接池,问题应该不会出在数据库连接上
[b]问题补充:[/b]
耗时在Hibernate执行查询上
[quote]去掉写入excel,依旧是慢[/quote]
[b]问题补充:[/b]
部分改为sql语句执行查询,速度有所提升,但全部改为sql有工作量
[b]问题补充:[/b]
先在开发环境(笔记本:xp/单核1.86GHZ/1G内存),用时5分钟
然后生产环境(服务器:2003server/4核2.33GHZ/4G内存),用时10多分钟
同样的数据库,同样的tomcat容器
速度整好差了1倍。想象中高配环境比低配环境要快才是,可结果诡异。
执行别的操作服务器还是比笔记本快好多,不知道为什么一干大活就掉链子呢?甚是诡异!
[b]问题补充:[/b]
服务器上的tomcat内存设置参数调整了一下,速度正常了,大概5分钟左右,说明跟jvm控制内存关系很大。
另改为了分页式的查询,每200个查询一次,速度有所提升,但不明显,服务器上可以提升半分钟。
[b]问题补充:[/b]
[quote]我们当初有一个功能,一次载入1.5W个对象,时间是2分钟左右,你10多分钟很有问题。[/quote]
不知您的导出有多少行多少列?每一行是否又涉及多个子查询?
[quote]不知您的导出有多少行多少列?每一行是否又涉及多个子查询?[/quote]
很早之前的事了,不过我记得最基本的字段在20个以上。没有子查询,子表lazy。
这个情况当初很糟糕,所以我们后面都改用分页的方式去获取数据。弹出对话框,说用户选择数据,而不是下拉框....-_-!
这个方法肯定不适合你啦。
[quote]服务器上的tomcat内存设置参数调整了一下,速度正常了,大概5分钟左右,说明跟jvm控制内存关系很大。[/quote]
你这样的处理方式是治标难治本哪!你的数据量就保持在这个数量级数上面没有再提升的空间?如果数据量加大了那你又要跑到服务器那边去加内存吗。。。
不知道你测试的“分页式的查询”是怎样的查询方式,我觉得这个处理方式是比较安全的,数据的增长对程序的稳定性方式会比较有保障。
额......我突然想到一个问题。你这么多数据导出来,你那Excel得几M啊?机器都这么吃不消,那多来几个人导数据那还得了。
还是有的数据是一些数据是附带的冗余数据?如果是的话那建议你去除掉这些数据。
怎么会这样?
如果查询越来越慢,数据库厂商就没必要再做下去了,性能毋庸置疑,出毛病的肯定是程序,用T-SQL或PL/SQL写连续查询时不会出现这样的问题,完毕。
没研究过Hibernate代码,这个不敢说,呵呵
持久层不就是起到方便连接数据库、操作数据库的作用么?
==有个问题忽视了
你的查询是怎么连的数据库?用了多少个连接?打开或关闭了多少次连接?应该是连接数量的问题吧
你都没有定位问题在哪里,很简单,在代码间插入计算耗时的代码就知道哪里慢了。
不一定是hql慢,我觉得可能是jxl在excel文件过大时很慢。
最好能把sql贴出来
是不是可能在Oracle 中查询过多数据缓存不够用?
你用的hql还是sql,hql还得解析成sql,解析也花时间
改吧,公司时间不够拿家里改也行。程序员嘛,应该不分工作地点,也没有时间限制,就一个目的,干自己感兴趣的,出高质量代码!
呵呵
session创建以后没有关闭吧。
导入的方式有问题,你应该先把数据全部取出来放在一个容器,然后从容器里取数据导出。
看你的问题好像是每导出一行你都要查一次库,那样数据库开销肯定会大。
我觉得你应该明确的找出系统慢的根源。
[quote]耗时在Hibernate执行查询上 [/quote]
虽然你说时间是消耗在Hibernate的查询上,但是显然有问题。我们当初有一个功能,一次载入1.5W个对象,时间是2分钟左右,你10多分钟很有问题。
可以把Hibernate的log调成Debug查看一下问题出在哪,Debug里头有很多宝贵的信息。
也可以使用jprofiler查看程序变慢的时候是哪些地方在工作,哪些对象在增长。
最后讲一下我的看法。你说程序会慢慢减速运行。那显然是哪一个值到达了极限,需要先释放掉一些数据再进行你下面的操作。这个值到底是在哪,只有你自己去调试。
然后你可以试一试这种方法。类似在做大批数据保存的时候,保存到一定数据量的时候去flush一下。你也可以把数据分段取出。当数据全部取出之后让它们脱离Hibernate的管理范围,也就是Detached状态,这样再来用jxl转成Excel。要知道java做几个循环还是很快的。
以上
期待你的分析结果。
其实我觉得你一开始的数据速度就有点问题了,1秒5-6行*7个语句。也就是1秒才能执行40个select。这个速度太慢了,就算hibernate也没那么慢的,除非查询本身就比较耗时。
要保持速度的话,你在每次hibernate查询完毕之后,都把session flush一次,应该就可以了。
hibernate的缓存可能是问题的症结之一,建议直接采用SQL,因为都是SELECT,及时关闭ResultSet会对内存空间释放。你这还是几个人测试,如果真正上线,用户一多,还有很多不定因素。
PS:可以试试FineReport(收费),再次声明我不是做广告。且跟此公司不相干。
估计内存不够你的数据也太多了吧。