You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot API生成百万级XLSX文件的最优方案及性能疑问

百万级记录XLSX生成服务的疑问解答

我的实现方案

我在API中实现了一个服务,可生成包含数千至百万条记录的XLSX文件,并返回其Base64文本。使用的依赖如下:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.2</version>
</dependency>

简要流程:先查询获取所有记录列表,再生成Excel文件,核心实现代码:

public static SXSSFWorkbook toExcel(List<?> listToExcel) {
    String[] headers = {"Column A",  .... , "Column n"};

    SXSSFWorkbook workbook = new SXSSFWorkbook(200);
    Sheet sheet = workbook.createSheet("Any Sheet Name");
    Row header = sheet.createRow(0);

    for (int i = 0; i < headers.length; i++) {
        Cell headerCell = header.createCell(i);
        headerCell.setCellValue(headers[i]);
        headerCell.setCellStyle(getStyle(workbook));
    }

    for (int i = 0; i < listToExcel.size(); i++) {
        Row row = sheet.createRow(i + 1);
        ObjectX report = (ObjectX) listToExcel.get(i);

        Cell cell = row.createCell(0);
        cell.setCellValue(report.getState());
        // 为对象的每个属性创建单元格,最终完成一行的构建
}

服务返回逻辑:

Workbook workbook = ObjectX.toExcel(listFromDatabase);
return ok(toBase64(workbook), "Consulta Exitosa");

疑问解答

1. 该方案的资源优化是否合理?

方向是对的,但还有优化空间:

  • 用SXSSFWorkbook设置内存保留200行,超过则刷盘,这避免了全量数据直接占满内存,是正确的流式处理思路。
  • 但你先把所有记录查进listFromDatabase,百万级数据的话这个列表本身会吃掉大量堆内存,建议改成分批查询数据库,查一批写一批,不用把全量数据存在内存里。
  • getStyle(workbook)如果每个单元格都调用,会生成大量重复样式对象,应该提前创建好样式实例,全局复用,减少内存开销和对象创建次数。
  • 转Base64时,别把整个文件读进内存再转换,改用流的方式逐步处理,避免一次性占用大内存。

2. 这是最快的XLSX生成方式吗?

不是。目前的实现还有更快的替代方案:

  • 如果不需要复杂格式(比如公式、单元格样式),或者能接受简化格式,阿里的EasyExcel比POI的SXSSF更快,它基于SAX解析,内存占用更低,流式写入效率更高。
  • 你的代码里逐个创建单元格的逻辑太繁琐,可以用反射或者预定义字段映射批量赋值,减少重复代码的执行开销。
  • 调整SXSSFWorkbook的内存保留行数(比如调到1000,根据服务器堆内存大小调整),减少刷盘频率,也能提升写入速度。

3. 该方案会影响Java堆内存或其他不可见的问题吗?

会有不少潜在问题:

  • 全量查询生成的listFromDatabase,百万级数据会直接占用大量堆内存,很容易触发OOM(内存溢出)。
  • SXSSFWorkbook虽然会刷盘,但内存中保留的行、样式对象、临时数据仍会占用内存,高并发场景下堆内存压力会很大。
  • 不可见隐患:SXSSF需要临时磁盘空间存放刷出的数据,如果磁盘满了会抛出IO异常;服务异常退出时,SXSSF的临时文件可能无法自动清理,长期堆积会占满磁盘;另外,Base64编码会比原文件大30%左右,百万级XLSX转Base64后响应体极大,不仅占服务器内存,还会增加网络传输时间,甚至触发网关的响应大小限制。

内容的提问来源于stack exchange,提问作者R.Ramirez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 03:55:27