本文目录导读:

是的,在 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:NULLExtra:Using where; Using filesort(未用索引排序)
解决方案:添加复合索引
// 迁移文件
Schema::table('users', function (Blueprint $table) {
$table->index(['last_login', 'created_at'], 'idx_last_login_created');
});
explain 后:
type:rangekey:idx_last_login_createdrows: 大幅减少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 |
添加排序字段到索引末尾 |
总结建议
- 任何可能导致慢查询的地方(
where、orderBy、join、groupBy)都跑一次explain()。 type出现ALL或Extra出现Using filesort是主要优化目标。- 不要只看
key不为空,还要看type和rows。type=index(全索引扫描)比type=ALL好不了太多。 - 索引不是越多越好——通过 explain 确认每个索引确实被用到,删除冗余索引。
一句话:在 Laravel 中,用 ->explain() 查看执行计划是索引优化的第一步,也是最重要的一步。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播