目录:
1. 背景
2. HSSH、 XSSF、SXSSF方案实现
3. HSSH、 XSSF、SXSSF方案对比
4. SXSSF、EasyExcel大数据量方案实现
5. SXSSF、EasyExcel大数据量方案对比
6. 性能优化策略
7. 业界其他方案
8. demo下载地址
背景
• 项目背景
XXXXXXXX项目,数据导出功能,由我负责设计优化方案及实现;
XXXXXXXX项目,也包含导出功能,也碰到导出数据性能问题;
XXX技术交流活动,整理了一遍材料跟大家一起交流学习;
• 解决了什么问题
用户需求:
1、需要导出数据,批量修改,然后导入系统批量刷数据;
2、导出数据需要做级联菜单、数据有效性控制;
3、需要导出大批量数据进行数据透视;
4、导出的文件,包含图片等;
性能问题:内存溢出,稳定性差;高并发下系统崩溃;
优化问题:原有功能不能有太大影响,不能投入太多人力;
用户体验问题:前端交互358原则,速度要快,功能要稳定,Excel下载下来后直接就能用等
HSSH、 XSSF、SXSSF方案实现
使用spring boot 简单搭建的工程项目,project 结构:
maven依赖
HSSH
XSSF
SXSSF
工具类,主要是遍历数据list,根据sheet创建row跟cell,兼容使用bean list跟map list,就不一一展示了,需要的可以下载demo查看;
HSSH、 XSSF、SXSSF方案对比
导出1W条数据,12个字段,其中2个备注大文本字段;单线程;本地环境,使用spring boot搭建的web服务,eclipse配置 Xmx1024m,启动时占用内存44M左右,堆大小320M左右
耗时 | 文件大小 | 内存 | cpu | |
HSSH (xls) | 5000条7min; 1W条36min | 1948KB | 启动的时候暴增,5000条后暴增; 800M左右 | 12%-15%,较稳定 |
XSSF (xlsx) | 1W条50min | 397KB | 950M左右 | 12%-15%,较稳定 |
SXSSF (xlsx) | 1W条3秒 10W25秒 | 929KB | 500M左右 | 峰值15%,稳定状态下0% |
SXSSF会将数据缓存到磁盘,旧的行数据不再出现在滑动窗口中并变得无法访问;最后将缓存合成一个文件的时候,会比较耗时间
我之前做过的优化方案,使用高配服务器,开并发查数据,导出50+字段,其中5个以上大文本字段,平均1W条数据耗时不超过1秒
Apache POI官方介绍:
User Model的缺点是一次性将文件读入内存,构建一颗Dom树.并且在POI对Excel的抽象中,每一行,每一个单元格都是一个对象.当文件大,数据量多的时候对内存的占用可想而知.
Event Model使用的方式是边读取边解析,并且不会将这些数据封装成Row,Cell这样的对象.而都只是普通的数字或者是字符串.并且这些解析出来的对象是不需要一直驻留在内存中,而是解析完使用后就可以回收
SXSSF、EasyExcel大数据量方案实现
SXSSF的实现,请查看前文;
EasyExcel:
SXSSF、EasyExcel大数据量方案对比
导出100W条数据,11个字段,其中1个备注大文本字段;单线程;本地环境,使用spring boot搭建的web服务, eclipse配置 Xmx1024m,启动时占用内存44M左右,堆大小320M左右
耗时 | 文件大小 | 内存 | cpu | 文件是否能打开 | |
SXSSF (xlsx) | 176秒 | 62902KB | 860M左右 | 12%左右 | 是,耗时较长 |
EasyExcel (xlsx) | 77秒 | 61678KB | 60M左右 | 12%左右 | 是,耗时较长 |
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够让原本一个3M的excel用POI sax依然需要100M左右内存降低到KB级别,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便(此处引用gitHub);
测试对比结果可能会因为实现的方式不一样,实际的结果可能出入也比较大,但是EasyExcel相对SXSSF来说有优化是肯定的。
性能优化策略
1. 服务化,功能分离单独部署,选择支持大数据量的框架
2. 提高服务器性能,CPU、内存、IO
3. 并发查询数据,使用队列写数据,分批次执行
4. 纯文本导出,去掉excel格式,这个点优化空间比较大
5. 去掉实时交互,改为数据中心交互;后端使用队列控制请求并发
6. …….
以上优化策略,为个人设计且实践过的方案,仅供参考,非喜勿喷。
业界其他方案
1. 纯文本CSV格式导出;需要对数据进行处理,清掉所有的特殊字符;
2. Easy poi、jxl
3. 直接调用数据库的Excel导出api
4. ……
抱歉,学海无涯,很多东西,我也只是听过。
一些程序员网友的评论:
网友:HSSH 单页65535行,早该淘汰了。 --好像是有这个限制,我没试过。
网友:百万级别还是建议用csv,直接写文本。 --我很早之前也使用过写文本的方式,但是要清理数据特殊字符等,最主要的是不满足项目需求,然后就放弃了。
网友:不太理解为什么有这种业务需求,你一顿华丽操作把几百万数据导出来,可是Excel并不能打开这么大的文件啊,导成csv不好么? --其实,解决不了问题的时候,把提出问题的人解决就好了,难不成真给人家做一款根据手机壳颜色变换主题的App啊。
网友:导出csv文件速度最快,Excel打开可以直接编辑,方便的很; --各有各的优缺点,有时候速度不一定是决定方案选择的唯一依据。
其实呢,方法多种多样,关键是满足项目需求,包括快速迭代交付需求,功能需求等等,至于用什么方式,重复造轮子啥的,看自己喜好咯。
demo下载地址
https://download.csdn.net/download/weixin_42686388/10780383