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

如何使用Laravel Eloquent优化关联大数据批量插入

优化Eloquent多关联批量插入的高效方案

你的问题我太熟悉了——嵌套循环加频繁的单条数据库查询,肯定会拖慢执行速度。咱们直接用批量插入把数据库操作次数砍到最少,同时保持代码简洁优雅,彻底解决超时问题。

核心思路

把原来多层嵌套的单条插入,改成三层批量插入的模式:

  1. 先批量创建所有Evaluation(每个Study对应一条)
  2. 再批量创建所有关联的Question(每个Evaluation对应38条)
  3. 最后批量创建所有关联的Answer(每个Question对应4条)
    同时用事务包裹整个流程,既保证数据一致性,又能进一步提升插入效率。

优化后的代码

use Illuminate\Support\Facades\DB;

Study::chunk(50, function ($studies) use ($request, $questionData, $answerData) {
    DB::transaction(function () use ($studies, $request, $questionData, $answerData) {
        // 1. 批量生成并插入所有Evaluation数据
        $evaluationEntries = $studies->map(function ($study) use ($request) {
            return [
                'study_id' => $study->id,
                'questionnaire' => $request->questionnaire,
                'description' => $request->description
                // 模型默认开启自动时间戳,created_at/updated_at会自动填充,无需手动添加
            ];
        })->toArray();

        // createMany会返回所有创建好的Evaluation模型实例(包含自增id)
        $evaluations = Evaluation::createMany($evaluationEntries);

        // 2. 批量生成并插入所有关联的Question数据
        $questionEntries = [];
        foreach ($evaluations as $evaluation) {
            foreach ($questionData as $qItem) {
                $questionEntries[] = array_merge(
                    $qItem,
                    ['evaluation_id' => $evaluation->id]
                );
            }
        }

        $questions = Question::createMany($questionEntries); // 对应你的question()关联模型

        // 3. 批量生成并插入所有关联的Answer数据
        $answerEntries = [];
        foreach ($questions as $question) {
            foreach ($answerData as $aItem) {
                $answerEntries[] = array_merge(
                    $aItem,
                    ['question_id' => $question->id]
                );
            }
        }

        Answer::createMany($answerEntries); // 对应你的answer()关联模型
    });
});

为什么这能大幅提升效率?

  • 砍断数据库交互次数:原来150个Study需要执行 150 + 150*38 + 150*38*4 = 28650 次数据库操作,现在每个50条的chunk只需要3次,总共9次操作,性能提升非常明显。
  • 事务优化:事务中的批量插入会合并提交,减少数据库的IO开销和锁竞争。
  • 降低内存占用:原来的循环会为每个关联都创建单独的模型实例,现在批量处理只需要一次性生成数据数组,内存压力小很多。

额外注意事项

  1. 确保你的模型开启了自动时间戳(默认是开启的),如果手动关闭了,需要在数据数组中手动添加created_at和updated_at字段。
  2. 如果questionData或answerData中有需要动态计算的字段(比如当前时间),可以在构造数组时统一处理,不要在循环里重复计算。
  3. 如果数据量极大(比如上万条),可以进一步调小chunk的大小,或者用insert代替createMany(insert不会创建模型实例,内存占用更低,但需要依赖自增主键的连续性来关联数据,适合无并发插入的场景)。

内容的提问来源于stack exchange,提问作者Rizky Irmawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 15:32:35