mysql如何查看SQL是否走索引_mysql执行计划分析方法

来源:这里教程网 时间:2026-02-28 20:51:58 作者:

EXPLAIN
看执行计划,这是最直接有效的判断方式

MySQL 不会主动告诉你“用了哪个索引”,但

EXPLAIN
会把优化器的决策摊开给你看。在你要分析的
SELECT
语句前加
EXPLAIN
,比如:

EXPLAIN SELECT * FROM users WHERE email = 'a@b.com';

重点关注这四列:

type
:值为
ALL
→ 全表扫描,没走索引;
const
/
eq_ref
/
ref
/
range
→ 通常走了索引
key
:非
NULL
(如显示
idx_email
)→ 实际使用了该索引
rows
:预估扫描行数,远小于表总行数才说明索引过滤有效;接近总数可能已失效
Extra
:出现
Using filesort
Using temporary
→ 即使走了索引,排序或分组仍可能回表或额外开销

注意:

key
非空 ≠ 高效,必须结合
type
rows
综合判断。

常见索引失效场景,一查就中招

很多 SQL 表面看着合理,其实根本没走索引。典型例子包括:

对索引列做隐式类型转换:
WHERE phone = 13800138000
phone
VARCHAR
),应写成
WHERE phone = '13800138000'
在索引列上使用函数:
WHERE YEAR(create_time) = 2023
→ 改用范围查询:
WHERE create_time >= '2023-01-01' AND create_time   
模糊查询以
%
开头:
LIKE '%abc'
→ 无法利用索引,可考虑全文索引或倒排结构
联合索引未满足最左前缀:
INDEX(a, b, c)
,但只查
WHERE b = 1
→ 不走索引;必须从
a
开始才有机会命中
索引列参与计算:
WHERE score + 10 > 90
→ 改为
WHERE score > 80

辅助验证:查索引是否存在、是否被真正用过

光看

EXPLAIN
还不够,得确认基础条件是否成立:

SHOW INDEX FROM users;
查表上有没有对应索引,以及索引列顺序是否匹配查询条件
performance_schema.table_io_waits_summary_by_index_usage
(MySQL 5.6+)看某索引实际被调用频次
查询
sys.schema_unused_indexes
(MySQL 5.7+ sys schema)识别长期零使用的冗余索引
开启慢查询日志(
slow_query_log=ON
),设
long_query_time=1
,捕获那些因未走索引而变慢的语句

这些不是替代

EXPLAIN
的手段,而是帮你定位“为什么明明建了索引却没被选中”。

进阶调试:用
OPTIMIZER_TRACE
看优化器怎么想的

EXPLAIN
显示没走索引,但你确信它“应该走”,就可以启用优化器跟踪:

SET optimizer_trace="enabled=on";
SELECT * FROM users WHERE age > 30;
SELECT * FROM information_schema.optimizer_trace;
SET optimizer_trace="enabled=off";

返回的 JSON 里会明确写出:“为什么放弃索引 idx_age?因为预估扫描行数占比太高,成本高于全表扫描”。这种细节,

EXPLAIN
不会告诉你。

真正容易被忽略的是:索引是否“被选中”和是否“高效”是两回事——

type=range
+
rows=10万
的查询,跟
type=ref
+
rows=2
的性能差距,可能比走不走索引还大。

相关推荐