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

使用Eloquent优化大表count查询:用户照片数量统计耗时过高如何解决

优化方案

1. 用预加载计数(withCount)解决N+1查询问题

你当前的写法属于典型的N+1查询场景:分页查询20个用户后,在视图循环中每个用户单独触发一次count查询,总共会产生21次SQL请求。Laravel提供了withCount方法可以在一次查询中完成所有关联数据的计数:
修改控制器代码如下:

public function show()
{
    $users = User::orderBy('username', 'ASC')
        ->withCount(['pictures' => function ($query) {
            // 匹配你原有查询的status=1、未软删的条件
            $query->where('status', 1);
        }])
        ->paginate(20);

    return view('admin.users', [
        'users' => $users,
    ]);
}

视图层直接读取预加载的计数字段即可,无需再触发关联查询:

{{ $user->pictures_count }}

2. 给pictures表加联合索引优化count查询速度

你的count查询筛选条件涉及user_id、status、deleted_at三个字段,新增联合索引可以让count查询直接走覆盖索引,不需要扫描全表数据,大幅降低查询耗时:
执行SQL建索引:

ALTER TABLE `pictures` ADD INDEX `idx_user_status_del` (`user_id`, `status`, `deleted_at`);

3. 新增冗余计数字段(适合高频统计场景)

如果用户照片数的统计展示频率非常高,可以在users表新增published_pictures_count整型字段,通过模型事件/观察者同步字段值:

  • 当新增符合status=1的照片记录时,对应user_id的计数字段+1
  • 当照片软删除、修改status为非1、硬删除时,对应user_id的计数字段-1
    优化后直接读取users表的冗余字段即可,不需要再查询pictures表,性能最高。

4. 缓存计数结果(适合实时性要求不高的场景)

如果对计数实时性要求不高,可以将用户照片数缓存到Redis等内存存储中,设置合适的过期时间(比如5-10分钟),请求时优先读取缓存,不存在再查数据库,降低数据库压力。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 19:30:00