耘朵
一只不务正业的程序媛
Toggle navigation
耘朵
主页
归档
标签
POI导出Excel优化速度方式
java
POI
2022-01-17 14:17:13
145
0
0
admin
java
POI
> 做Excel导出的时候,业务要求至少能导出10W条,复查了之前人写的代码,有很多问题,逐步优化。 ### 1. 导出的Controller里,返回的是一个Result类 返回的是一个Result类,但是response里又set了response.setContentType("application/vnd.ms-excel;charset=UTF-8");这就很矛盾。告诉了要返回一个excel,可是如果出现异常了,又返回了一个json? 这里改掉。 **解决方式:** - 返回改成void ### 2. 数据库查询很慢 数据库使用的是Oracle数据库,很多都是现学的。 **解决办法:** - 首先看了下sql语句,同时left join了某张表多次,想到最后也没想到解决办法,有说利用视图的,但是不太会。 然后又看了下数据库,吓坏我了,一个索引都没有,主索引都没有,先加索引吧。感觉没有太大提升。 - 据说语句全换成大写的,也能提升一点,换。 - 然后看sql,发现他的sql再做分页的时候冗余太多,数据库总共68W多条数据,每次他都要全查出来再分页,这样会导致单页数据的导出也很慢,大概写下优化后的sql ```sql SELECT * FROM ( SELECT ROWNUM ROWNUM_, 其他字段 FROM 查询的表 CAR LEFT JOIN 一堆其他的表 WHERE 查询条件 AND ROWNUM <= 要查的行数上限 ) WHERE ROWNUM_>要查的行数下限 ``` 这样查,如果你查100-200条的时候, 就先给你筛出来200条了。那基数就是200,从这里面再取出100行已后的数据,就快很多,反之,上限要是和下限都写在括号外的话,那基数就是真个数据库的68W,不慢才怪。下面放个图片看下两个优化前后的对比   ### 3. 导出时先写Excel进服务器文件再从文件入的response流 代码中,整个流程我打了个log测试,查数据库要40S,查完之后数据库的List要转成的是WORKBOOK,花了1分半左右,然后将这个WORKBOOK写入服务器做个xlsx的文件,又花了1分半左右,最后把这个文件再转成响应流回到前端。 **解决办法:** - 首先,这个转到服务器再从服务器转回前端的过程就没必要,就直接把这个WORKBOOK直接写到response流里被 ```java Workbook excel = 创建Excel的方法,略; excel.write(response.getOutputStream()); ``` 就是这么简单,比写各种流转换简单多了 - 然后啊,不知道有没有人发现, 上面的代码里,用的是Workbook,这就会出现一个问题,数据量大的时候,就内存溢出了。网上找到一个靠谱的解决办法 [https://www.cnblogs.com/wanghaiwei/p/9930601.html 参考文章](https://www.cnblogs.com/wanghaiwei/p/9930601.html) 简单来说,就是使用SXSSFWorkbook,设置大小,超出的就写入磁盘,这样有很多临时文件,最后要清除一下。 ```java SXSSFWorkbook excel = 创建Excel的方法,略; response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("表名", "UTF-8")); response.flushBuffer(); excel.write(response.getOutputStream()); excel.dispose(); ``` 虽然是为了解决内存溢出问题,但是,速度一下从2分半提升到了30秒 
上一篇:
IDEA好用工具
下一篇:
多线程并发
0
赞
145 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
文档导航