为啥POI的SXSSFWorkbook占用内存更小

SXSSFWorkbook(Streaming XSSF Workbook)是 Apache POI 提供的一种 流式 Excel 写入 实现,相比传统的 XSSFWorkbook,它通过 临时文件缓存行级刷新 机制,显著降低了内存占用。以下是其核心优化原理:


1. XSSFWorkbook 的问题(全内存存储)

XSSFWorkbook 在写入 Excel(.xlsx)时:

  • 所有数据存储在内存(DOM 方式),包括:
    • 单元格数据
    • 样式信息
    • 公式计算
  • 内存占用 = 文件大小 × 放大系数(通常 3-5 倍)
    • 例如:100MB 的 Excel 文件,可能需要 300MB~500MB 内存。
  • 大文件容易 OOM(OutOfMemoryError)。

2. SXSSFWorkbook 的优化(流式写入)

SXSSFWorkbook 通过以下方式减少内存占用:

(1)行级缓存 + 临时文件

机制说明
只缓存部分行默认缓存 100 行(可配置),超出部分写入临时文件(磁盘)。
临时文件存储使用 java.io.tmpdir 存储溢出的行数据,减少内存压力。
按需加载读取时从临时文件恢复数据,而非全量加载到内存。

(2)手动刷新(flushRows

  • 可主动调用 sheet.flushRows() 强制将缓存行写入磁盘,释放内存。
  • 示例:
    for (int i = 0; i < 1_000_000; i++) {
        SXSSFRow row = sheet.createRow(i);
        row.createCell(0).setCellValue("Row " + i);
        if (i % 10_000 == 0) {
            sheet.flushRows(); // 每 1 万行刷新一次
        }
    }
    

(3)样式共享

  • 样式(CellStyle)和字体(Font)会被复用,避免重复创建。
  • 通过 Workbook.createCellStyle() 集中管理样式。

(4)自动清理临时文件

  • 调用 workbook.dispose() 后,自动删除临时文件:
    try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) {
        // 写入数据...
    } // 自动调用 dispose()
    

3. 内存对比(XSSF vs SXSSF

场景XSSFWorkbookSXSSFWorkbook
存储方式全内存 DOM内存 + 磁盘临时文件
内存占用高(文件大小 × 3~5 倍)低(仅缓存指定行数)
适用数据量小文件(<10MB)大文件(百万行+)
OOM 风险

4. 适用场景

(1)适合 SXSSF 的情况

  • 导出 百万行级 Excel 报表。
  • 内存有限(如云服务器、容器环境)。
  • 需要长时间运行的批处理任务。

(2)适合 XSSF 的情况

  • 小文件(<10MB)快速处理。
  • 需要复杂样式、公式计算。
  • 频繁随机访问单元格(SXSSF 不支持随机修改已刷新的行)。

5. 注意事项

  1. 临时文件目录

    • 默认使用 java.io.tmpdir,确保磁盘空间充足。
    • 可通过 System.setProperty("java.io.tmpdir", "/custom/tmp") 修改。
  2. 不可逆操作

    • SXSSF 写入磁盘后的行无法再修改(只支持追加)。
  3. 性能权衡

    • 内存换速度:SXSSFXSSF 稍慢(因涉及磁盘 I/O)。
  4. 资源释放

    • 必须调用 workbook.dispose(),否则临时文件可能残留。

6. 代码优化建议

// 1. 设置缓存行数(根据数据量调整)
SXSSFWorkbook workbook = new SXSSFWorkbook(1000); 

// 2. 写入数据时定期刷新
for (int i = 0; i < 1_000_000; i++) {
    SXSSFRow row = sheet.createRow(i);
    // ...
    if (i % 10_000 == 0) {
        sheet.flushRows();
    }
}

// 3. 最终保存并清理
try (FileOutputStream fos = new FileOutputStream("big-data.xlsx")) {
    workbook.write(fos);
}
workbook.dispose(); // 清理临时文件

总结

SXSSFWorkbook 通过 行级缓存 + 临时文件 的流式写入机制,将内存占用从 O(文件大小) 降低到 O(缓存行数),成为处理大 Excel 文件的 首选方案
但需注意 不可逆写入临时文件管理,避免资源泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思静鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值