Laravel按status分组每组获取指定数量结果的性能优化方案
按status分组获取每组前3条数据的性能优化方案
需求背景
需要按status字段对Comic模型数据分组,每组获取最多3条更新时间最新的记录。
原实现方案
最初采用先查询全量数据,再在Collection层面处理分组和截取:
Comic::latest("updated_at")->get()->groupBy("status")->map(function ($item) { return $item->take(3); });
问题点:该方案会将comics表的所有数据加载到内存中,当数据量增大时,会导致数据库查询耗时增加、内存占用过高,性能瓶颈凸显。
SQL层面优化方案
使用数据库窗口函数ROW_NUMBER()直接在查询阶段完成分组和截取,避免全量数据加载:
Comic::latest("updated_at") ->fromSub('select *, ROW_NUMBER() OVER (PARTITION BY status ORDER BY updated_at DESC) as RowNumber from comics', 'x') ->where('RowNumber', '<=', 3) ->get();
原理说明:
- 子查询中通过
PARTITION BY status按状态分组,ORDER BY updated_at DESC保证每组内按更新时间倒序排序 ROW_NUMBER()为每组内的记录分配唯一行号- 外层查询筛选行号≤3的记录,直接得到每组前3条最新数据
内容的提问来源于stack exchange,提问作者Tai Nguyen
相关产品推荐
相关产品推荐

