Heycm

Heycm

百万数据流导出Excel

2024-08-24
百万数据流导出Excel

碰到需要导出大量数据的时候,通常需要做异步、分批、多线程处理,避免请求挂太久超时、占用资源太多、撑爆内存等等。

代码

其实很简单,一眼秒懂,不想看测试的可以直接跳过了

代码在这点我点我 https://gitee.com/heycm/online-heycm-excel-export/tree/master

思路

这里是一个小案例,使用 MyBatis + EasyExcel 实现一个流式导出的功能,并做了一些测试,做个参考,基本思路是这样:

  1. 设计一个 ExcelHanlder 文件导出处理器,实现 ResultHandler 接口的 handleResult 方法,该方法在流式查询时,每次从流中获取一行数据时被调用;

  2. 设定一个批次的最大数量值,在 handleResult 方法中完成数据行对应导出数据的转换并收集到一个内存容器 List

  3. 当 List 达到批次容量时,或当 handleResult 返回最后一行数据时,触发写文件动作;

  4. MyBatis 使用流查询,并使用 ExcelHandler 作为处理器,就可以了。

一般我会将 ExcelHandler 设计成一个抽象类,将批次容量值和具体的数据转换过程交由子类实现,因为一套流程大体是不会改变的,使用模板方法是设计可以方便其他导出业务来复用。

一些测试

测试是按 10w 为一个批次,每个批次写一个 Sheet 页,导出一kun个百万行数据,主要是限制了 JVM 内存 250MB,然后观察 GC 情况,和导出耗时

耗时:45秒多点

EFB1478E-6CF6-4DF3-A54B-63CABBECBD82.png

JVM

9A60C01C-28A4-415E-9A3F-F784CACFF649.pngAA0976A6-71CD-4211-B020-024CC9B98DBA.png

YGC 吃了快 1.5 秒,没有 OGC ,勉勉强强,这还是没有什么业务逻辑的情况下的表现,如果需要在转换过程还要做一些数据清洗加解密还会慢很多。

其他想法

  • 大量数据的导出,通常还需要配合异步任务来执行

  • 做独立的线程池去专门处理异步任务,避免吃掉其他服务的资源

  • 甚至于,给这个线程池分配单独的内存空间、硬件资源,不过这一块不是很了解,有机会学习学习。