mysql如何查看SQL是否走索引_mysql查询优化技巧

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

直接看
EXPLAIN
key
type
字段

这是最快速、最可靠的判断方式。只要

key
列非
NULL
,且
type
不是
ALL
index
(全索引扫描),基本就走索引了。

type = ref
eq_ref
:走了二级索引或主键/唯一索引,效果好
type = range
:走了索引范围扫描(如
WHERE age BETWEEN 25 AND 35
type = ALL
:没走索引,全表扫描——性能杀手,优先优化
key
为空或显示
NULL
:即使有索引,也没被选中

示例:

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

如果返回中

key: idx_email
type: ref
,说明成功命中索引;若
key: NULL
+
type: ALL
,就得继续排查原因。

为什么有索引却没走?常见踩坑点

建了索引 ≠ 查询自动用索引。MySQL 优化器会基于成本估算决定是否使用,而“成本低”不等于“有索引就一定用”。

隐式类型转换:
WHERE user_id = '123'
user_id
INT
)→ 触发全表扫描,因为字符串转整数会让索引失效
对索引列用函数:
WHERE YEAR(create_time) = 2024
→ 索引无法下推,改写为
create_time BETWEEN '2024-01-01' AND '2024-12-31'
前导模糊匹配:
WHERE name LIKE '%abc'
→ B+树无法从左匹配,索引失效;
LIKE 'abc%'
可用
索引选择性太低:比如给只有两个值的
gender
列建索引,优化器大概率放弃它
数据量极小(如几百行):优化器可能认为全表扫描比回表+索引查找更快

辅助验证:查索引是否存在 & 是否被统计

有时你以为有索引,其实根本没建,或者建错列了。用这两条命令交叉验证:

查索引定义:
SHOW INDEX FROM users;
确认
Column_name
Key_name
是否符合预期(比如你查
email
,但索引建在
user_email
上)
查索引统计信息(反映优化器“认知”):
SELECT * FROM mysql.innodb_index_stats WHERE database_name = 'your_db' AND table_name = 'users';
n_diff_pfx01
(基数)异常低,说明统计过期,可手动更新:
ANALYZE TABLE users;

进阶定位:用
optimizer_trace
看优化器真实决策

EXPLAIN
显示没走索引,但你觉得“它应该走”,就可以打开优化器跟踪,看它到底怎么想的:

SET optimizer_trace="enabled=on";
SELECT * FROM users WHERE status = 1 AND created_at > '2025-01-01';
SELECT * FROM information_schema.optimizer_trace\G
SET optimizer_trace="enabled=off";

重点关注

analyzing_range_alternatives
using_index_for_order_by
段落,里面会明确写出:“该索引成本为 123.45,全表扫描成本为 89.12,故选择后者”。这才是真正的原因,不是玄学。

注意:

optimizer_trace
是会话级的,别忘了关;而且它只对当前会话生效,不能查别人跑的 SQL。

相关推荐