处理poi导出数据oom溢出

163 阅读2分钟

场景

最近公司开发一个项目,项目中使用到word导出,使用的方案是 poi-tl,一开始还好几乎可以满足所有场景,直到遇到一个需求。

需求的场景是在 word 表格中插入明细数据,没有添加这部分之前都是没问题的,添加这部分之后整个导出就慢了,直到上预发环境把真实数据导到库中之后直接没办法导出了,报了 oom 溢出的问题。

处理思路

第一想到的是把堆内存调大,所以在启动的时候直接给了 4 个G的内存,但是通过测试发现有些数据量较小的可以导出,大概3W条数据的样子,但是当数据量超过这导出的时候还是会报错,当前的想法是导出 word 的问题,如果修改为导出 excle 会不会更好。
修改为 excle 导出之后发现还是不行,虽然比 word 导出的数据量多了些,但是还是没办法解决这个问题。
后来就猜测会不会是因为 poi 导出的时候会把所有的数据加载到内存当中,同时所有的数据虽然没有给样式什么的,但是 poi 可能会给到默认样式,所以就造成了导出的文件虽然只有几十兆,但是在程序中会占几个G 的内存。

解决方案

解决办法就是使用 poi 提供的方法,不要全部一次性写入文件,而是分批写入,方法如下:

// 设置每次写入的值
SXSSFWorkbook resultWb = new SXSSFWorkbook(100);
//创建sheet
Sheet sheet = resultWb.createSheet();

通过这个方式就可以导出海量数据了,本地测试导出一百万条数据大概在一分多钟,具体的这个值设置多大看机器和业务场景了,测试的 100、5000、10000、2000 导出一百万条数据的时间,分别是 1分30秒、一分20秒、一分18秒、一分21秒,区别并不是很大。