mysql如何通过索引减少表扫描_mysql执行效率提升

2次阅读

加了索引仍全表扫描,主因是查询未满足最左前缀、like前置通配、索引列用函数或隐式类型转换;需用explain看type(非all)和key(非NULL)确认走索引;高区分度、高频过滤/排序字段优先建索引,联合索引按过滤性强+频率高排序;覆盖索引可避免回表,但要求select字段全在索引中。

mysql如何通过索引减少表扫描_mysql执行效率提升

为什么加了索引还是全表扫描?

mysql 并不总是用索引,即使字段上有索引。常见原因是查询条件未触发索引的最左前缀匹配,比如对 name 建了联合索引 (name, age),但查询写成 WHERE age = 25,这时索引完全失效。另外,LIKE 以通配符开头(如 LIKE '%abc')、在索引列上使用函数(如 WHERE UPPER(name) = 'ABC')或隐式类型转换(如字符串字段传入数字)都会导致索引失效。

如何确认某条 SQL 是否走了索引?

必须用 EXPLAIN 看执行计划,重点关注 typekey 字段:typerefrangeconst 表示走了索引;key 显示实际使用的索引名;若 keyNULLtypeALL,就是全表扫描。

示例:

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

如果 email 有索引且查询无干扰操作,type 应为 refkey 显示索引名。

哪些字段适合建索引?

不是所有字段都该加索引。优先考虑:

  • WHERE、JOIN、ORDER BY、GROUP BY 中高频出现的列
  • 区分度高的列(如 user_idgender 更适合单列索引)
  • 联合索引按「过滤性强 + 查询频率高」的顺序排列,例如常查 WHERE status = ? AND created_at > ?,且 status 取值少,created_at 区分度高,则应建 (created_at, status) 而非反过来
  • 避免在频繁更新的字段上建过多索引,会拖慢写入性能

覆盖索引能彻底避免回表吗?

可以,但前提是 SELECT 的所有字段都在索引中。比如表有 idnameemail,建了联合索引 (email, name),那么 SELECT name, email FROM users WHERE email = 'x' 就是覆盖索引查询,Extra 显示 using index,无需回主键索引查数据行。

但如果写成 SELECT * 或包含 id(不在索引里),就会回表——这是最容易被忽略的性能损耗点。

真正要减少扫描,核心不是“有没有索引”,而是“查询是否能只靠索引完成”。

text=ZqhQzanResources