该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-26
抛个砖:
先确定几个可行的原则: 1、尽早的释放数据库连接 2、尽可能少的创建对象 3、用临时文件来代替jvm中的临时对象,缩短值对象的生命周期 4、缓存 ResultSet循环取值的时候,调用一个callback接口,该接口负责将各字段值直接放入到临时文件中。 interface ResultSetPersistCallback { void appendRow(rs); } TextPersistCallback的具体实现是将每一行以csv的格式append到临时的文本文件中,这个没啥好说的,直接使用append模式的File即可 XlsPersistCallback的具体实现是每一行附加到临时的Excel中,这个比较麻烦了(POI的实现中,仍然在jvm中构建HSSFWorkbook对象图,最后一次性写入xls文件,并且每个sheet还有65536的最大行限制),貌似没有好的方案能够缩短值对象的生命周期。 rs循环完毕,释放数据库资源,关闭临时文件,维护缓存池,文件流发送到客户端。 缓存池结构: key: sql key value: CachedFile class CachedFile{ String filepath; long creationTime; long period; } 当然还少不了一个scheduler去掉过期的缓存和临时文件。 |
|
返回顶楼 | |
发表时间:2007-04-26
内存爆掉很好解决,使用线程池限制生成xls的并发数量不就得了。
|
|
返回顶楼 | |
发表时间:2007-04-26
to sorphi:
谢谢你提供的方案 事实上类似的方案我也提了 但是由于系统中根本就没考虑到callback的设计 现在的dao都是写死的 改动比较大 已经被我们老大驳回了 :'( |
|
返回顶楼 | |
发表时间:2007-04-26
fins,写完之后才发现你也提到了xls的写入才是瓶颈。
而且我刚才想了一下,我的方法中callback导致第2/3三条和第1条是冲突的。 既然方法被驳回了,那也说得过去。那就集中解决xls的生成问题吧 刚才google了一下csv -> xls的东西,虽然没找到什么有效的java代码,但是发现一个有趣的事情,有网站专门提供在线的转换。继而想到,何不单独提供一个应用来干这个事情呢? 不过用java来做这种转换,仍然摆脱不了内存占用较大的问题,看poi的API。jxl的我不清楚,照你说的,跟poi的差不多。 既然客户比较“变态”(查询这么贼多数据),那么何不让这种转换拿到client端来做呢?哈哈 继续google,activex+csv+xls http://www.softinterface.com/Convert-Excel-ActiveX/Convert-Excel-ActiveX.htm |
|
返回顶楼 | |
发表时间:2007-04-26
考虑生成跟下载分成两个步骤。 另外既然内存占用那么多,jvm的内存调优也要考虑
|
|
返回顶楼 | |
发表时间:2007-04-26
sorphi 写道 fins,写完之后才发现你也提到了xls的写入才是瓶颈。
而且我刚才想了一下,我的方法中callback导致第2/3三条和第1条是冲突的。 既然方法被驳回了,那也说得过去。那就集中解决xls的生成问题吧 刚才google了一下csv -> xls的东西,虽然没找到什么有效的java代码,但是发现一个有趣的事情,有网站专门提供在线的转换。继而想到,何不单独提供一个应用来干这个事情呢? 不过用java来做这种转换,仍然摆脱不了内存占用较大的问题,看poi的API。jxl的我不清楚,照你说的,跟poi的差不多。 既然客户比较“变态”(查询这么贼多数据),那么何不让这种转换拿到client端来做呢?哈哈 继续google,activex+csv+xls http://www.softinterface.com/Convert-Excel-ActiveX/Convert-Excel-ActiveX.htm 我说的不太准确 其实是两个瓶颈 一个是 collection对象 一个是jxl生成的xls大对象 郁闷中 我打算研究一下excel的生成原理 自己做一个合并xls文件的程序 把多个文件 合并成一个有多个sheet页的xls文件 (用jxl poi做这类操作还是会生成很大很大的对象) |
|
返回顶楼 | |
发表时间:2007-04-27
解决你的 excel问题,可以考虑生成csv。先在服务器生成一个临时文件来存放csv问题,然后查询数据,取数据放入stringBuffer 当此stringBuffer的数据大到一定程度时候就往文件里输出,然后清空StringBuffer 这样重复处理,直到查询出来的数据都写人文件。这样因该可以避免java的outofmemory。
|
|
返回顶楼 | |
发表时间:2007-04-27
fins 写道 我说的不太准确 其实是两个瓶颈 一个是 collection对象 一个是jxl生成的xls大对象 郁闷中 我打算研究一下excel的生成原理 自己做一个合并xls文件的程序 把多个文件 合并成一个有多个sheet页的xls文件 (用jxl poi做这类操作还是会生成很大很大的对象) 1. 对于生成xls文件,我有一些经验。 我用的POI。我发现,对于同样是将2万行的数据写入一个文件,放在一个sheet里和两个sheet里,内存占用能相差一倍,后者少。经过我的试验,一般一个sheet里1万行(一行有10几列)比较合适,多的就分sheet保存,可以有效的降低内存占用,约1--n倍。 虽然不是终极的解决方案,也是一个可行的方案,不妨试试。 2. csv是简单文本格式,内存占用量必定比xls少很多倍,但是他基本上无法表达格式。实在不行就用csv好了。 3. 还有一个曲线救国的方法,就是用html格式,技巧是,将html文件保存成xls后缀文件(假装为xls),excel是可以自动识别为html并打开,也可以保存格式。唯一的不同是,用户需要“真实”的xls格式的话,需要用Excel打开后另存为xls格式。其实用户不就是打印么,那么应该没有区别。 |
|
返回顶楼 | |
发表时间:2007-04-27
programmer 写道 解决你的 excel问题,可以考虑生成csv。先在服务器生成一个临时文件来存放csv问题,然后查询数据,取数据放入stringBuffer 当此stringBuffer的数据大到一定程度时候就往文件里输出,然后清空StringBuffer 这样重复处理,直到查询出来的数据都写人文件。这样因该可以避免java的outofmemory。
类似的方法我们用过 我们是直接将 response.getOutputStream传入dao 在dao里生成 printwriter 然后直接 out.print 这个方法应该更好 避免了生成和修改文件 |
|
返回顶楼 | |
发表时间:2007-04-27
Lucas Lee 写道 fins 写道 我说的不太准确 其实是两个瓶颈 一个是 collection对象 一个是jxl生成的xls大对象 郁闷中 我打算研究一下excel的生成原理 自己做一个合并xls文件的程序 把多个文件 合并成一个有多个sheet页的xls文件 (用jxl poi做这类操作还是会生成很大很大的对象) 1. 对于生成xls文件,我有一些经验。 我用的POI。我发现,对于同样是将2万行的数据写入一个文件,放在一个sheet里和两个sheet里,内存占用能相差一倍,后者少。经过我的试验,一般一个sheet里1万行(一行有10几列)比较合适,多的就分sheet保存,可以有效的降低内存占用,约1--n倍。 虽然不是终极的解决方案,也是一个可行的方案,不妨试试。 2. csv是简单文本格式,内存占用量必定比xls少很多倍,但是他基本上无法表达格式。实在不行就用csv好了。 3. 还有一个曲线救国的方法,就是用html格式,技巧是,将html文件保存成xls后缀文件(假装为xls),excel是可以自动识别为html并打开,也可以保存格式。唯一的不同是,用户需要“真实”的xls格式的话,需要用Excel打开后另存为xls格式。其实用户不就是打印么,那么应该没有区别。 1 3 策略我们现在的系统都用到了 问题就是老系统 我主贴中提到的是一个老系统 郁闷啊 不过还是谢谢大家提供的方案 其实仔细看看,可以说,楼上各位的方案基本上已经涵盖了 所有的 xls的解决方法 我可以把这个帖子作为一个 方法的汇总帖了 呵呵 谢谢各位!!! 如果我们老大允许我们大刀阔斧的改造代码 一切就都OK了 现在也许问题已经不是出在方法和技巧上 而是人的问题了 以前系统设计的不够好 ,让现在的人为过去埋单,似乎也是天经地义的.毕竟我也从前辈那学到过太多的东西 呵呵 再次谢谢大家 |
|
返回顶楼 | |