转载请注明出处,如有问题请联系我们! Laravel 数据库查询优化:后台列表变慢时怎么排查
Laravel 数据库查询优化:后台列表变慢时怎么排查 这篇文章适合后台列表越来越慢、订单页打开很久、文章管理加载卡顿的 Laravel 项目。很多时候不是服务器配置太低,而是查询写法、索引和分页出了问题。
一、先判断慢在哪里
后台变慢可能有三个原因:
- 数据库查询慢。
- PHP 逻辑循环太多。
- 前端一次渲染数据太多。
先不要急着加服务器,应该先定位。
二、开启查询日志
在本地或测试环境可以临时开启 Laravel 查询日志:
DB::enableQueryLog();
// 执行业务查询
dd(DB::getQueryLog());
线上不建议长期开启,因为会占用内存。
三、典型问题:N+1 查询
比如订单列表,每个订单都去查一次用户:
$orders = Order::paginate(20);
foreach($orders as $order){
echo $order->user->name;
}
如果没有预加载,就可能产生 1 次订单查询 + 20 次用户查询。正确写法:
$orders = Order::with("user")->paginate(20);
四、列表页必须分页
后台列表不要使用 all() 一次性取全部数据。
// 不推荐
$orders = Order::all();
// 推荐
$orders = Order::orderByDesc("id")->paginate(20);
如果数据量大,分页是最基础的优化。
五、只查询需要的字段
后台列表通常不需要取详情字段、长文本字段。
$articles = Article::select("id", "title", "created_at", "status")
->orderByDesc("id")
->paginate(20);
如果 body、content 这类大字段也被取出来,会影响数据库和网络传输。
六、给常用筛选字段加索引
常见需要加索引的字段:
- where 经常查询的字段。
- orderBy 经常排序的字段。
- join 关联字段。
- 状态 + 时间组合筛选字段。
ALTER TABLE orders ADD INDEX idx_user_id (user_id);
ALTER TABLE orders ADD INDEX idx_status_created (status, created_at);
ALTER TABLE articles ADD INDEX idx_status_id (status, id);
七、用 explain 看是否走索引
EXPLAIN SELECT * FROM orders WHERE status=1 ORDER BY created_at DESC LIMIT 20;
如果 type 是 ALL,说明可能全表扫描;如果 key 为空,说明没有用到索引。
八、统计数据不要每次实时算
后台首页常见的订单总数、今日新增、销售额统计,如果每次刷新都实时 count 和 sum,数据量大后会很慢。可以缓存:
$todayCount = Cache::remember("today_order_count", 300, function(){
return Order::whereDate("created_at", today())->count();
});
九、常见错误
- 循环中查询数据库。
- 列表页没有分页。
- select * 取出大字段。
- 索引加在不常用字段上。
- 缓存没有过期策略。
十、总结
Laravel 查询优化的顺序是:先定位慢查询,再解决 N+1,再分页和减少字段,最后加索引和缓存。不要一开始就堆服务器配置,很多后台慢的问题,一条错误查询就能拖垮整个页面。
