1.调研总结
1.1.poi的介绍:
HSSF:Excel97-2003版本,扩展名为.xls。一个sheet最大行数65536,最大列数256。
XSSF:Excel2007版本开始,扩展名为.xlsx。一个sheet最大行数1048576,最大列数16384。
SXSSF:是在XSSF基础上,POI3.8版本开始提供的支持低内存占用的操作方式,扩展名为.xlsx。
1.2阿里开发easyexecl的初衷:
poi 旧版本03, 07 会出现内存溢出问题
sxssf版本对内存问题做了优化,满足大部分需求,但阿里主要是为了满足高并发导入,高并发时poi有bug,且poi没及时维护Bug,故此,阿里自己读取execl时候改用为不一次性加载数据进内存中,而改为加载到磁盘,虽然速度可能慢了,但是不会OOM(内存溢出),
大部分企业数据量不大且没有高并发,所以poi是能满足的。主要是读方面比较厉害。对于内存需要启用多少,官方文档也有对应的计算公式,不过一般我们调大点就好,远比poi能省很多内存。对于10来w的数据easyexecl也可以强制开启走内存模式,当然如果是低数据量,我们根本可以不用使用它。
1.3有可能的问题(仅是调研,实验才能定论)
Eeayexecl 和poi有部分版本出现冲突
使用最新版本3.0.5,旧版本有些许bug
可能会出现使用中部分api报错
官方qq群回复不算很及时
官方文档常见问题库不多
二.资料链接
Eeayexecl官方文档:alibaba-easyexcel.github.io/index.html(…
最新官方文档 : yuque.com/easyexcel
官方解答qq群:496594404
三.Eeayexecl基本概述(摘抄官方文档)
1.其他框架缺点
1.1Excel读写时候内存溢出
虽然POI是目前使用最多的用来做excel解析的框架,但这个框架并不那么完美。大部分使用POI都是使用他的userModel模式。userModel的好处是上手容易使用简单,随便拷贝个代码跑一下,剩下就是写业务转换了,虽然转换也要写上百行代码,相对比较好理解。然而userModel模式最大的问题是在于非常大的内存消耗,一个几兆的文件解析要用掉上百兆的内存。现在很多应用采用这种模式,之所以还正常在跑一定是并发不大,并发上来后一定会OOM或者频繁的full gc。
1.2其他开源框架使用复杂
对POI有过深入了解的估计才知道原来POI还有SAX模式。但SAX模式相对比较复杂,excel有03和07两种版本,两个版本数据存储方式截然不同,sax解析方式也各不一样。想要了解清楚这两种解析方式,才去写代码测试,估计两天时间是需要的。再加上即使解析完,要转换到自己业务模型还要很多繁琐的代码。总体下来感觉至少需要三天,由于代码复杂,后续维护成本巨大。
1.3其他开源框架存在一些BUG修复不及时
由于我们的系统大多数都是大并发的情况下运行的,在大并发情况下,我们会发现poi存在一些bug,如果让POI团队修复估计遥遥无期了。所以我们在easyexcel对这些bug做了规避。
2.读写性能官方说法
64M内存20秒读取75M(46W行25列)的Excel(3.0.2+版本)
3.优化核心原理(对比poi)
3.1 核心原理
写有大量数据的xlsx文件时,POI为我们提供了SXSSFWorkBook类来处理,这个类的处理机制是当内存中的数据条数达到一个极限数量的时候就flush这部分数据,再依次处理余下的数据,这个在大多数场景能够满足需求。
读有大量数据的文件时,使用WorkBook处理就不行了,因为POI对文件是先将文件中的cell读入内存,生成一个树的结构(针对Excel中的每个sheet,使用TreeMap存储sheet中的行)。如果数据量比较大,则同样会产生java.lang.OutOfMemoryError: Java heap space错误。POI官方推荐使用“XSSF and SAX(event API)”方式来解决。
分析清楚POI后要解决OOM有3个关键。
3.2文件解压文件读取通过文件形式
3.3避免将全部全部数据一次加载到内存,采用sax模式一行一行解析,并将一行的解析结果以观察者的模式通知处理。
3.4、抛弃不重要的数据
Excel解析时候会包含样式,字体,宽度等数据,但这些数据是我们不关心的,如果将这部分数据抛弃可以大大降低内存使用。Excel中数据如下Style占了相当大的空间。
四.Eeayexecl实测百万数据导入导出
1.导入实测
1.1实验测试条件说明
该测试只考虑读取execl解析数据部分,不考虑分批进入数据库部分
100w execl数据源如下文件:
1.2贴图
1.2.1代码贴图
主函数:
监听器(读取部分execl数据后就会调用该方法进行入库处理):
实体类:
1.2.2性能贴图
jps查看测试的进程号
jconsole pid 调用起监控内存软件
1.3测试结果
2min钟左右,内存占据200多m,不像poi那样内存爆炸
2.导出实测
1.1实验测试条件说明
数据源:list加载100w数据
实际开发中应该是从库里分批读取,然后调用阿里api,故不会有什么内存问题
1.2贴图
主函数:
实体类(注意属性加注解问题)
1.3测试结果
3字段 15s
9个字段 20s
15个字段 31s