分批次处理百万级数据导入需流式读取、边读边处理、批量入库。用easyexcel流式读+自定义listener控制对象生命周期,jdbc批量写入+游标分页,可选csv+load data优化,全程内存可控。

分批次处理百万级数据导入,核心是打破“全量加载→全量解析→全量入库”的链路,把内存占用压在可控范围内。关键不在工具多炫,而在每一步都主动控制数据驻留时长和对象生命周期。
用 EasyExcel 流式读 + 自定义 Listener
别调 EasyExcel.read().sheet().doRead() 一把梭——它默认会缓存所有解析结果。必须用带泛型的 read(ExcelType.XLSX, new AnalysisEventListener<datadto>() {...})</datadto> 方式,让框架边读边触发 invoke() 回调:
- 每次只把一行 Excel 数据转成 Java 对象,处理完立刻丢弃,不进 List、不进 Map
- 在
invoke()里做校验、转换、临时缓存(比如攒够 1000 条再批量 insert) - 重写
doAfterAllAnalysed()做收尾,比如刷入剩余未满批的数据、清理资源
数据库写入用 JDBC 批量 + 游标分页
避免 MyBatis 的 insertBatch() 封装层偷偷缓存全部参数。直接用原生 JDBC 的 addBatch() + executeBatch():
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 每 1000–5000 行执行一次 batch,具体看单行数据大小和数据库连接配置
- 查询阶段禁用 offset 分页,改用游标:
WHERE id > #{lastId} ORDER BY id LIMIT #{batchSize} - MyBatis 的
<select></select>标签加上fetchSize="1000",提示 JDBC 驱动流式拉取 ResultSet,减少内存缓冲
绕过 Excel 解析,走 CSV + LOAD DATA
如果业务允许(比如后台运维导入、无样式要求),这是性能天花板方案:
- 用 EasyExcel 先把 Excel 流式转成 CSV 文件(不加载全量,逐行读+逐行写)
- Java 调用 MySQL 的
LOAD DATA LOCAL INFILE,由数据库服务端直接解析文件入库 - 全程 Java 内存只保留单行数据对象 + 小缓冲区,实测百万行导入可压到 50MB 以内
线程与资源必须显式管控
异步不是万能药,乱用反而放大 OOM 风险:
- 导入任务别扔进公共线程池,单独配一个有界队列的线程池(比如 core=2, max=4)
- 每个 Listener 实例绑定一个 Connection 或 PreparedStatement,用完立即
close() - 临时文件(如 Excel 转 CSV 中间文件)写完立刻删除,或用
Files.createTempFile()让 JVM 自动清理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










