转载请注明出处,如有问题请联系我们! 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,再分页和减少字段,最后加索引和缓存。不要一开始就堆服务器配置,很多后台慢的问题,一条错误查询就能拖垮整个页面。

标签云