为什么加了索引还是全表扫描?
MySQL 并不总是用索引,即使字段上有索引。常见原因是查询条件未触发索引的最左前缀匹配,比如对
name建了联合索引
(name, age),但查询写成
WHERE age = 25,这时索引完全失效。另外,
LIKE以通配符开头(如
LIKE '%abc')、在索引列上使用函数(如
WHERE UPPER(name) = 'ABC')或隐式类型转换(如字符串字段传入数字)都会导致索引失效。
如何确认某条 SQL 是否走了索引?
必须用
EXPLAIN看执行计划,重点关注
type和
key字段:
type是
ref、
range或
const表示走了索引;
key显示实际使用的索引名;若
key为
NULL或
type是
ALL,就是全表扫描。
示例:
EXPLAIN SELECT * FROM users WHERE email = 'a@b.com';
如果
type应为
ref,
key显示索引名。
哪些字段适合建索引?
不是所有字段都该加索引。优先考虑:
WHERE、JOIN、ORDER BY、GROUP BY 中高频出现的列 区分度高的列(如user_id比
gender更适合单列索引) 联合索引按「过滤性强 + 查询频率高」的顺序排列,例如常查
WHERE status = ? AND created_at > ?,且
status取值少,
created_at区分度高,则应建
(created_at, status)而非反过来 避免在频繁更新的字段上建过多索引,会拖慢写入性能
覆盖索引能彻底避免回表吗?
可以,但前提是
SELECT的所有字段都在索引中。比如表有
id、
name、
(email, name),那么
SELECT name, email FROM users WHERE email = 'x'就是覆盖索引查询,
Extra显示
Using index,无需回主键索引查数据行。
但如果写成
SELECT *或包含
id(不在索引里),就会回表——这是最容易被忽略的性能损耗点。
真正要减少扫描,核心不是“有没有索引”,而是“查询是否能只靠索引完成”。
