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
相关产品推荐
相关产品推荐

