Laravel索引用explain分析吗

wen PHP项目 26

本文目录导读:

Laravel索引用explain分析吗

  1. 如何在 Laravel 中使用 Explain
  2. Explain 结果关键字段解读(特别注意索引相关)
  3. 实际调试示例:发现问题 + 添加索引
  4. 调试工具与扩展
  5. 常见索引问题 + Explain 特征
  6. 总结建议

是的,在 Laravel 中分析数据库索引性能时,强烈建议使用 explain 方法

Laravel 的查询构建器(Query Builder)和 Eloquent ORM 都原生支持生成 EXPLAIN 语句,帮助你分析 SQL 执行计划,判断索引是否被有效使用。


如何在 Laravel 中使用 Explain

Laravel 提供了 explain() 方法,可以直接链式调用:

// 原始查询
$sql = DB::table('users')
    ->where('email', 'like', '%@gmail.com')
    ->toSql();
// 获取 Explain 结果
$explain = DB::table('users')
    ->where('email', 'like', '%@gmail.com')
    ->explain();
dd($explain); // 输出索引使用情况

如果你是用的 Eloquent 模型

$explain = User::where('status', 'active')
    ->orderBy('created_at', 'desc')
    ->explain();
dd($explain);

注意explain() 返回的是一个集合(Collection),每条记录对应一个执行计划行(如果是复杂查询可能有多个表)。


Explain 结果关键字段解读(特别注意索引相关)

字段 含义 索引相关判断
type 访问类型(性能从好到差) const / eq_ref / ref / range 表示用到了索引;ALL 表示全表扫描(最差)
possible_keys 可能用到的索引 列出了可选的索引
key 实际使用的索引 如果为 NULL,表示没有使用索引
key_len 使用的索引长度 越短越好,但复合索引要看是否用到了前缀
rows 扫描的行数 行数越少,索引效率越高
Extra 额外信息 Using index(覆盖索引)、Using where(回表)、Using filesort(未用索引排序,危险)

典型好索引 vs 坏索引示例

查询 type key rows
WHERE id = 1 const PRIMARY 1 ✅ 最好
WHERE email = 'test@test.com' ref users_email_unique 1 ✅ 好
WHERE age > 18 range idx_age 1000 ⚠️ 可接受
WHERE name LIKE '%张三%' ALL NULL 100万 ❌ 全表扫描
ORDER BY created_at 无索引 ALL + Using filesort NULL 100万 ❌ 最差

实际调试示例:发现问题 + 添加索引

问题场景

// 查询未使用索引
$users = DB::table('users')
    ->where('last_login', '>', now()->subDays(30))
    ->orderBy('created_at')
    ->get();
// 执行 explain
$explain = DB::table('users')
    ->where('last_login', '>', now()->subDays(30))
    ->orderBy('created_at')
    ->explain();

Explain 结果

  • type: ALL(全表扫描)
  • key: NULL
  • Extra: Using where; Using filesort(未用索引排序)

解决方案:添加复合索引

// 迁移文件
Schema::table('users', function (Blueprint $table) {
    $table->index(['last_login', 'created_at'], 'idx_last_login_created');
});

explain 后:

  • type: range
  • key: idx_last_login_created
  • rows: 大幅减少
  • Extra: Using where; Using index(排序也通过索引完成)

调试工具与扩展

1 Laravel Debugbar

安装 barryvdh/laravel-debugbar,可以直接在浏览器底部看到每条 SQL 的 Explain 执行计划(需在配置中启用 explain 功能)。

2 全局记录慢查询 + Explain

// AppServiceProvider 的 boot 方法
DB::listen(function ($query) {
    if ($query->time > 1000) { // 超过1秒
        $explain = DB::select("EXPLAIN " . $query->sql, $query->bindings);
        Log::channel('slow_sql')->info('Slow query explain:', [
            'sql' => $query->sql,
            'explain' => $explain,
        ]);
    }
});

3 Tinker 交互式调试

php artisan tinker
> $explain = DB::table('orders')->where('total', '>', 100)->explain();
> $explain->toArray();

常见索引问题 + Explain 特征

问题 Explain 特征 解决方案
全表扫描 type: ALL, key: NULL 添加合适的单列或复合索引
索引列参与函数运算 type: ALL, Extra: Using where 改为 WHERE date(created_at) = '...'WHERE created_at >= '...' AND created_at < '...'
模糊查询以 开头 type: ALL, key: NULL 考虑全文索引或搜索引擎
复合索引前缀缺失 type: ref/key: idx_a_b 但只用了 a 调整查询顺序或重建复合索引
排序未用索引 Extra: Using filesort 添加排序字段到索引末尾

总结建议

  1. 任何可能导致慢查询的地方whereorderByjoingroupBy)都跑一次 explain()
  2. type 出现 ALLExtra 出现 Using filesort 是主要优化目标。
  3. 不要只看 key 不为空,还要看 typerowstype=index(全索引扫描)比 type=ALL 好不了太多。
  4. 索引不是越多越好——通过 explain 确认每个索引确实被用到,删除冗余索引。

一句话:在 Laravel 中,用 ->explain() 查看执行计划是索引优化的第一步,也是最重要的一步。

抱歉,评论功能暂时关闭!