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

如何修复Laravel Excel Reader内存泄漏?maatwebsite/excel导入内存过高

内存过高的核心原因

  1. 错误使用toCollection方法:Excel::toCollection()的设计逻辑是将Excel内所有符合要求的行最终合并为单个完整集合返回,即便你配置了WithChunkReading分块读取,所有分块的行数据依然会被逐步累加保存在内存中直到读取完成,本质还是全量加载,分块逻辑在这里只负责降低单次读取的峰值,不会减少总内存占用。
  2. ShouldQueue接口未生效:你给Import类加了ShouldQueue,但依然使用同步调用的toCollection方法,队列异步处理逻辑完全没有触发,反而额外增加了对象序列化的开销,进一步拉高内存占用。
  3. 冗余数据被加载:底层依赖的PhpSpreadsheet默认会加载Excel的单元格样式、格式、公式等非数据内容,加上你配置了表头从第15行开始,前面14行的空白/无效内容也会被底层解析加载,额外占用大量内存。

优化方案

1. 替换toCollection为import方法

Excel::import()不会将所有行合并返回,处理完单个分块后会自动释放该分块的内存,不会累计内存占用,调整后调用代码如下:

try {
     Excel::import(
         new UsersImport(
             $entity,
             $user,
             $unique_fields,
             $update_duplicates,
             new JobHistory,
             $this->userTypeRepository,
         ),
         storage_path().'/uploads/' . $usersFileName
     );
   } catch (\Throwable $th) {
      throw new Exception($th);
}

2. 正确使用队列或移除队列配置

如果需要异步处理导入,将调用方法改为Excel::queueImport(),此时每个分块会作为独立队列任务执行,单任务仅持有当前分块的内存,不会累计。如果不需要异步导入,直接将ShouldQueue接口从Import类中移除,减少不必要的开销。

3. 禁用非必要内容加载

在Import类中添加读取配置,仅加载纯数据,跳过样式、格式、无效行的解析:
可以在config/excel.php中全局配置,也可以在Import类中添加WithReadConcern接口指定只读数据,同时添加读过滤器跳过前14行无效内容,避免冗余数据占用内存。

4. 移除未使用的特性

你当前代码中WithEvents接口的registerEvents返回为空,RemembersChunkOffset特质如果没有用到偏移记录的需求,都可以直接删除,减少对象的内存占用和序列化开销。

5. 手动触发垃圾回收

在collection方法的末尾添加gc_collect_cycles(),强制PHP回收当前分块处理产生的废弃内存,进一步降低内存峰值。

优化完成后,导入800条数据的内存占用会控制在几十MB级别,完全不需要4GB内存。


内容的提问来源于stack exchange,提问作者PHP User

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 01:51:03