前言
对于百万,甚至千万以上量级的数据导出,需要注意:
①内存方面:通常jvm内存都是有上限的,数据量太大一次性读到堆内存容易oom
②效率方面:数据量太大如果还是用单线程,往往会很慢
为了解决上述问题,我们可以考虑将数据分批次读入内存,然后利用多线程实现边读边写,从而提高导出效率
1、事先可以利用一些工具查看导出的单个对象大小,如jol-core包
-
引入依赖
<!-- 对象大小可以用jol-core包查看--> <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency> -
打印出单个对象大小
ClassLayout layout = ClassLayout.parseInstance(new User()); System.out.println(layout.toPrintable()); -
或者利用JDK自带的Runtime类:
runtime.totalMemory() - runtime.freeMemory()计算Runtime runtime = Runtime.getRuntime(); long memory = runtime.totalMemory() - runtime.freeMemory(); log.info("Memory used by the list: " + memory + " bytes"); -
内存总消耗 = 单对象大小 * 导出数据数量,从而计算出一次性load到内存所需要的空间,如果计算出的内存总消耗超出目前系统分配的堆内存70%大小(预留30%),则考虑分批次load表数据到内存,防止OOM。 -
本次我设置的jvm参数如下:
-Xms1536M -Xmx1536M -Xmn512M -Xss256K -XX:SurvivorRatio=6 -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M
2、使用阿里的EasyExcel实现文件导出
EasyExcel 通过流式处理架构、分批次加载和内存优化设计,从数据解析、对象管理到资源释放全链路控制内存占用,从而避免传统 Excel 工具(如POI)因全量数据加载导致的 OOM 问题
- 基于 SXSSFWorkbook 的流式写入
EasyExcel 使用 Apache POI 的 SXSSFWorkbook 实现流式写入,数据按批次(默认每 100 行)生成临时文件块,而非一次性加载到内存 (临时文件块默认存储在磁盘上,而非内存中,这是其能够处理海量数据且避免内存溢出(OOM)的核心机制),显著减少内存占用。- 分批次数据加载
在处理百万级数据时,通过分片读取和写入(如每次处理 1000 行),避免一次性加载全量数据到堆内存
- 引入pom依赖
<!-- easyexcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency> <!-- jpa --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> - 创建导出实体类User(这里偷个懒,导出实体类和数据库实体共用…建议还是最好分开定义)
@Data @NoArgsConstructor @Table(name="user") @Entity public class User{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id"

最低0.47元/天 解锁文章
646

被折叠的 条评论
为什么被折叠?



