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

Laravel查询15万+MySQL记录响应慢报500错如何优化

性能问题核心原因

当前代码属于典型的N+1查询反模式:先执行1次查询拉取全部900条Population数据,再循环对每条Population单独发起1次COUNT查询,累计产生901次数据库请求,大量连接开销、网络IO是性能差的首要原因。
另外你目前创建的是4个字段的单列索引,MySQL单表查询一次最多只能选择一个最优的单列索引使用,其余过滤条件需要回表逐行判断,无法通过索引一次性完成所有过滤逻辑,所以加了索引也没有明显性能提升。

具体优化方案
  • 合并零散查询为单条聚合查询,消除N+1问题
    把900次循环COUNT的逻辑替换为一次分组聚合查询,直接在数据库侧完成所有population_id的计数统计,总查询次数从901次降到2次,Laravel实现代码如下:

    // 一次性统计所有符合条件的关联记录数,返回 [population_id => 计数] 的映射数组
    $validRecipientCount = Recipient::selectRaw('population_id, COUNT(*) as total')
        ->whereIn('employment_condition', [0,1,3])
        ->where('has_car', '!=', 0)
        ->where('has_land', '!=', 0)
        ->groupBy('population_id')
        ->pluck('total', 'population_id')
        ->toArray();
    
    // 拉取Population全量数据,映射统计结果
    $pops = Population::all()->map(function ($pop) use ($validRecipientCount) {
        $pop['count'] = $validRecipientCount[$pop->id] ?? 0;
        return $pop;
    });
    

    如果已经在模型中定义了Population和Recipient的一对多关联,也可以直接用框架自带的withCount方法实现,底层逻辑和上述代码一致:

    $pops = Population::withCount([
        'recipients' => function ($query) {
            $query->whereIn('employment_condition', [0,1,3])
                ->where('has_car', '!=', 0)
                ->where('has_land', '!=', 0);
        }
    ])->get();
    
  • 替换单列索引为联合覆盖索引,消除回表开销
    针对这个固定查询场景,删除之前建的4个单列索引,创建如下联合覆盖索引:

    ALTER TABLE recipients ADD INDEX idx_pop_filter (population_id, employment_condition, has_car, has_land);
    

    该索引按照等值匹配优先的顺序排列字段,查询时可以直接在索引树上完成过滤、分组、计数全流程,不需要回表读取行数据,查询效率会有数量级提升。

  • 可选进阶优化(适合高频查询场景)
    如果该统计接口调用频率很高,可以在Population表新增valid_recipient_count字段,在Recipient数据新增、修改、删除时,同步更新对应关联Population的计数值,查询时直接读取该字段即可,不需要每次实时聚合统计,响应时间可以降到毫秒级。

注意事项

建立联合索引时,不要把带!=的不等值条件放在索引最左侧,不等值条件区分度低,会大幅降低索引过滤效率,上述索引顺序已经将等值匹配的population_id、employment_condition放在靠前位置,能最大化索引利用率。

内容的提问来源于stack exchange,提问作者Mohammed Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:39:23