索引覆盖指查询所需字段全部被索引列覆盖,无需回表,从而提升性能;判断依据是explain中extra显示“using index”;设计需遵循最左前缀、高区分度字段靠左、返回字段纳入索引末尾。

什么是索引覆盖,为什么它能提升查询性能
索引覆盖是指一条查询语句所需的所有字段,全部被某个索引的列(包括键列和包含列)所“覆盖”,无需回表查聚簇索引。这意味着数据库引擎只扫描索引就能返回结果,跳过了访问数据页的开销。
例如:用户表 users(id, name, email, age, city),主键是 id,另建组合索引 INDEX idx_city_age_name (city, age, name)。执行:
SELECT name FROM users WHERE city = 'Beijing' AND age = 28;
该查询只用到 city、age(过滤条件)和 name(返回字段),三者都在索引中——这就是典型的覆盖索引查询。
如何判断一个查询是否走索引覆盖
核心看 EXPLAIN 输出中的 Extra 列:
- 出现 Using index → 走了覆盖索引
- 出现 Using where; Using index → 过滤+覆盖,仍高效
- 出现 Using index condition → 用了ICP(索引条件下推),但未必覆盖
- 若含 Using filesort 或 Using temporary,即使有索引,也不代表覆盖
注意:SELECT * 几乎不可能被覆盖(除非是聚簇索引本身),应避免在高并发查询中使用。
组合索引设计的三个关键原则
组合索引不是字段堆砌,而是按访问模式精心排列:
- 最左前缀原则必须遵守:只有从左到右连续匹配的字段才能命中索引。比如 (a,b,c) 支持 WHERE a=1、WHERE a=1 AND b=2、WHERE a=1 AND b=2 AND c=3,但不支持 WHERE b=2 或 WHERE c=3
- 过滤性强的字段放左边:高频且高区分度的列(如 status、type)优先;低区分度字段(如 gender 只有男/女)尽量靠后,或考虑是否值得入索引
- 把查询中要返回的字段“拖”进来:为实现覆盖,在满足最左前缀前提下,把 SELECT 列或 ORDER BY 列加到索引末尾(用 INCLUDE 或直接作为索引列)。例如查询常按 city 筛选并按 age 排序,返回 name,索引可设为 (city, age, name)
常见陷阱与优化建议
面试中常考“看似合理实则无效”的索引设计:
- 给 WHERE 中用 OR 连接的多个字段各建单列索引 → 多数情况下 MySQL 只选其一,应改用组合索引或重写为 UNION
- 对 VARCHAR(500) 字段全列建索引 → 浪费空间且降低写性能,应加前缀长度(如 INDEX idx_title (title(100))),前提是前100字符足够区分
- 在 ORDER BY 字段上单独建索引,但 WHERE 条件未命中该索引 → 排序无法利用索引,会触发 filesort。应让 WHERE + ORDER BY 共同落在同一组合索引中
- 忽略隐式类型转换:如字段是 VARCHAR,但查询写成 WHERE col = 123(传整型)→ 索引失效。应保持类型一致
实际设计时,先梳理高频 SQL 的 WHERE、GROUP BY、ORDER BY、SELECT 四类子句,再按“过滤→排序→返回”顺序组织索引列。










