根本原因是数据在内存中积压,需实现“边读、边转、边写”的流式处理:数据库查询启用流式拉取,Excel写入使用流式Writer,中间处理零缓冲,超限数据主动分片。

用 Stream API 导出大规模 Excel 时,内存占用高的根本原因不是库本身,而是数据在内存中“积压”——比如一次性查百万行、全量构建工作表模型、或样式/公式反复计算。真正有效的调优,是让数据像水流一样“边读、边转、边写”,全程不囤积。
数据库查询必须流式拉取
避免 SELECT * FROM table 全量加载。改用数据库原生流支持:
- MySQL:启用
useCursorFetch=true+fetchSize(如 5000),配合 JDBC 的ResultSet.next()迭代 - PostgreSQL:使用
cursor-based pagination(WHERE id > ? ORDER BY id LIMIT N)替代 OFFSET - Node.js 场景:用
pg.Cursor或mysql2/promise的stream()方法直接返回 Readable Stream - Java 场景:MyBatis 配合
@Select("...") @Options(fetchSize = 5000),或 Spring Data JPA 的StreamfindAllBy(...)
Excel 写入必须启用流式 Writer
禁用任何「先建完整对象再保存」的模式。关键动作是绕过内存 DOM 树:
诊断并修复涉及公式、命名范围、Power Query 刷新、数据透视表、VBA/宏保存等问题的 Microsoft Excel XLSX 工作簿
- Go(Excelize):用
f.NewStreamWriter("Sheet1"),逐行调用SetRow(),最后Flush() - Java(EasyExcel / SXSSF):EasyExcel 用
write(dataList, writeSheet).doWrite()自动流式;SXSSF 必须设new SXSSFWorkbook(100)(窗口保留 100 行),并关闭setCompressTempFiles(false)防止临时文件膨胀 - Node.js(ExcelJS):必须用
workbook.stream.write(res)+worksheet.addRow(...),且禁用addWorksheet({ properties: { tabColor: ... } })等样式初始化 - 通用原则:关掉共享字符串表(
EnableSharedStrings=false)、禁用自动筛选、跳过合并单元格逻辑
中间处理环节要零缓冲
数据从 DB 流到 Excel 流之间,不要落地为 List 或 Map 集合:
- 用生成器(Java 的
Iterator/ Go 的chan/ Node.js 的AsyncGenerator)按需吐数据 - 字段映射尽量简单:避免
new HashMap().put("name", obj.getName()),直接传数组或结构体 - 时间/数字格式统一前置转换,不在写入时调用
SimpleDateFormat.format()或toLocaleString() - 如有清洗逻辑(如脱敏、空值替换),写成无状态函数,不缓存上下文
导出超限数据要主动分片
单 Sheet 最多 1048576 行,硬超会报错。不能靠“等它崩了再切”,而要主动控制:
- 每写满 95 万行,就
workbook.addSheet("Sheet" + ++index)新建表 - 分片依据主键递增列(如
id或create_time),确保可并行、无重叠 - 文件名带时间戳和分片标识,如
export_20260512_001.xlsx - 前端下载页提供 ZIP 合包链接,后端用
zip-stream(Node)或ZipOutputStream(Java)边生成边压缩
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










