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

Laravel大数据库查询优化:关联用户与Sedes数据性能问题

优化Laravel多对多关联查询,解决N+1性能问题

嘿,太懂你这种被N+1查询折腾的痛苦了——2000次数据库请求绝对会让页面加载慢到离谱,咱们直接把筛选逻辑搬到数据库层面,一次性解决这个问题!

核心优化思路:用Eloquent关联筛选替代PHP循环

你的需求是筛选出关联了管理员拥有的任意一个Sedes的role_id=3的用户,完全不需要把所有用户都拉到PHP里再循环判断。我们可以用Laravel的whereHas方法,直接在数据库查询时就完成关联过滤。

优化后的代码(基础版)

// 先拿到当前管理员拥有的Sedes ID数组
$sedesHabilitadas = auth()->user()->sedes->pluck('id')->toArray();

// 直接查询符合条件的用户,同时预加载sedes避免后续隐性查询
$habilitados = Usuario::with(['sedes'])
    ->where('role_id', 3)
    ->whereHas('sedes', function ($query) use ($sedesHabilitadas) {
        // 筛选出关联了指定Sedes的用户
        $query->whereIn('sedes.id', $sedesHabilitadas);
    })
    ->get();

为什么这能解决性能问题?

  • 原来的实现:1次查询所有role_id=3的用户 + 2000次查询每个用户的sedes = 总共2001次数据库请求
  • 优化后:1次查询管理员的Sedes ID + 1次查询符合条件的用户(同时预加载sedes)= 总共2次数据库请求

数据库天生擅长做这类集合关联筛选,比在PHP里循环判断高效得多,数据量越大,性能提升越明显。

进阶优化:合并查询减少请求次数

如果想进一步减少查询次数,可以把获取管理员Sedes ID的逻辑改成子查询,这样只需要1次数据库请求就能拿到结果:

$habilitados = Usuario::with(['sedes'])
    ->where('role_id', 3)
    ->whereHas('sedes', function ($query) {
        $query->whereIn('sedes.id', function ($subquery) {
            // 子查询直接从中间表获取当前管理员的Sedes ID
            $subquery->select('sedes_id')
                ->from('users_sedes')
                ->where('user_id', auth()->id());
        });
    })
    ->get();

额外小提示

如果你的Datatable列表不需要展示用户关联的Sedes信息,可以去掉with(['sedes']),这样还能节省内存和查询时间,进一步提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:19:51