索引覆盖指查询仅通过索引B+树叶子节点获取全部数据,无需回表;EXPLAIN中出现Using index即表示成功覆盖。
判断一个SQL查询是否能走索引覆盖,核心看SELECT字段和WHERE条件字段是否全部被同一个索引包含,且该索引的列顺序满足最左前缀原则;一旦需要回表,说明索引中缺失了查询所需的部分列(尤其是SELECT中的非索引列或ORDER BY/GROUP BY中未被覆盖的列)。
当一条查询语句执行时,仅通过B+树的叶子节点就能获取所有需要的数据,无需回主键索引(聚簇索引)查找整行记录,就称为“索引覆盖”。此时执行计划中会出现 Using index 标识。
SELECT name, age FROM user WHERE city = 'Beijing' → 可索引覆盖;SELECT name, age, id FROM user WHERE city = 'Beijing' → 不一定覆盖(id 是主键,InnoDB 中二级索引叶子节点存的是主键值,所以仍可能免回表;但若查的是 email 这类非索引列,必然回表)。只要查询中出现任何未被当前使用索引包含的列(包括 SELECT、ORDER BY、GROUP BY、HAVING 中引用的列),且该列不属于该索引定义的一部分,就会触发回表。
SELECT a,b,c → c 导致回表;ORDE
R BY a, b DESC → 可能无法利用索引排序,优化器可能放弃覆盖而选择回表+文件排序;WHERE YEAR(create_time) = 2025,即使 create_time 有索引,也无法用上索引覆盖(索引失效+需计算后比对)。直接看 EXPLAIN 结果中的 Extra 列:
不是索引越多越好,而是要让高频查询的“查询列 + 过滤列 + 排序列”尽量落在同一索引中: