覆盖索引指索引包含查询所需全部字段(SELECT、WHERE、ORDER BY、GROUP BY列),使MySQL直接从B+树叶子节点获取数据而无需回表;主键索引天然覆盖,二级索引需显式包含所有相关字段。
覆盖索引能避免回表,核心是让查询所需的所有字段都包含在索引中,这样 MySQL 直接从索引 B+ 树叶子节点拿到全部数据,无需再回聚簇索引查找行记录。
当一个索引包含了查询中 SELECT 列 + WHERE/ORDER BY/GROUP BY 涉及的列 时,该索引就称为“覆盖索引”。MySQL 优化器会优先选择它,因为执行计划中 Extra 字段会显示 Using index,表示只用索引没回表。
注意:主键索引(聚簇索引)本身存储完整行数据,所以任何基于主键的单列查询天然就是覆盖的;但普通二级索引默认只存索引列 + 主键值,因此要覆盖,就得把查询用到的字段全加进索引里。
关键原则是:把 高频查询中 SELECT 的字段 + 过滤/排序/分组字段 合理组合进一个联合索引,且遵循最左前缀原则。
例如:查询 SELECT name, email FROM user WHERE status = 1 AND create_time > '2025-01-01' ORDER BY id;
推荐索引:INDEX idx_cover (status, create_time, name, email, id)。
其中 status 等值匹配,create_time 范围过滤,name/email/id 覆盖输出和排序——这样整条语句不回表。
用 EXPLAIN 查看执行计划,重点关注两处:
小技巧:用 SELECT * 很难走覆盖索引,尽量明确列出需要的字段,并确保它们都在索引中。
覆盖索引不是万能的,要注意以下几点:
LIKE '%abc')无法使用索引,自然也无法覆盖不复杂但容易忽略。