本文详解 laravel 使用工厂批量生成百万级测试数据时出现内存耗尽问题的根本原因并提供基于分批处理、关系预加载和原生批量插入的实战优化方案。 本文详解 laravel 使用工厂批量生成百万级测试数据时出现内存耗尽问题的根本原因并提供基于分批处理、关系预加载和原生批量插入的实战优化方案。在 Laravel 项目中使用 Eloquent 工厂Factories进行大规模数据填充如 seeding 百万级 Term 和关联 Question时开发者常遭遇“Allowed memory size exhausted”错误——即使逻辑上看似每次循环都重置变量如 $terms内存仍持续增长直至崩溃。根本原因并非 PHP 变量未释放而是 Eloquent 的对象持久化机制与 N1 查询模式叠加导致的内存与数据库双重瓶颈。? 问题本质1N 查询 持久化对象累积原始代码中$this-command-withProgressBar(array_fill(1, $count, ), function ($item) { $terms Term::factory(10)-create(); // ? 创建 10 个 Term触发 10 次 INSERT $terms-each(function ($term) { $term-questions()-saveMany( // ? 对每个 Term 触发 10 次 Question INSERT共 100 次/轮 Question::factory(10)-make([term_id $term-id]) ); });});每轮迭代创建 10 个 Term再为每个 Term 创建 10 个 Question → 单轮即执行 110 次数据库写入10 10×10saveMany() 会为每个 Question 实例调用 save()触发完整 Eloquent 生命周期模型实例化、事件分发、属性赋值、查询构建等所有模型对象在循环结束前驻留内存withProgressBar 的闭包内无显式垃圾回收Eloquent 模型及其关联关系如 questions() 关系实例持续累积导致内存线性增长 —— 这正是 i ≈ 2000 时崩溃的直接原因。? 正确解法三阶优化策略1?? 分批控制Batching—— 降低单次内存压力避免一次性创建过多模型实例改用 chunk 或手动分块$count 1_000_000;$batchSize 500; // 每批处理 500 个 Term而非 10,000 轮 × 10for ($i 0; $i $count; $i $batchSize) { $terms Term::factory()-count($batchSize)-create(); // 批量生成 Question 数据不实例化模型 $questions []; foreach ($terms as $term) { for ($j 0; $j 10; $j) { $questions[] [ term_id $term-id, content fake()-sentence(), created_at now(), updated_at now(), ]; } } // 原生批量插入绕过 Eloquent 开销 DB::table(questions)-insert($questions); // 强制释放内存可选但推荐 unset($terms, $questions); gc_collect_cycles();}2?? 禁用模型事件与延迟加载关键性能开关在 seeding 过程中关闭非必要开销 Mokker AI AI产品图添加背景