如何通过MySQL执行计划Extra列的Using Index判断索引使用效率?
- 内容介绍
- 文章标签
- 相关推荐
本文共计950个文字,预计阅读时间需要4分钟。
Extra 列表中出现 Using index 是好事,但不等于没有索引问题——它只说明使用了覆盖索引,不代表查询设计合理、索引结构最优,更不意味着没有冗余字段或顺序缺失。
怎么一眼看出 Using index 是真覆盖还是假高效
覆盖索引的本质是:查询中 SELECT 的所有列 + WHERE 用到的所有列,全部落在同一个索引的最左前缀范围内。
常见误判点:
- 有
Using index,但WHERE条件用了函数(如WHERE YEAR(hire_time) = 2023)→ 实际走不了索引范围扫描,type可能是index或ALL,性能仍差 - 索引是
(name, age, position),但查询写成SELECT * FROM employees WHERE age = 25→ 不满足最左前缀,Extra不会显示Using index,哪怕age在索引里 -
SELECT中包含TEXT或BLOB字段 → 即使其他字段被索引覆盖,InnoDB 也无法把大字段存进二级索引页,Using index不会出现
Using index 和 Using where; Using index 的关键区别在哪
两者都表示走了覆盖索引,但过滤动作发生的层级不同,直接影响扫描行数和响应稳定性:
-
Using index:整个WHERE条件都能用索引精确匹配或范围扫描(比如WHERE name = 'Alice' AND age BETWEEN 20 AND 30),引擎层直接筛完,不回表也不在 server 层再过滤 -
Using where; Using index:索引覆盖了所有字段,但WHERE中有无法下推到引擎层的条件,例如LIKE '%suffix'、IS NULL、或者涉及隐式类型转换(如字符串字段查WHERE status = 1)→ 这些条件必须由 server 层对引擎返回的每一行再做一次判断 - 实际影响:
Using where; Using index的rows值往往偏高,因为引擎返回了更多中间结果;而filtered列如果远低于 100,就是 server 层过滤掉大量数据的信号
为什么有时加了索引却看不到 Using index
不是索引没生效,而是“覆盖”这个前提没达成。几个高频漏点:
-
SELECT *:除非是聚簇索引(主键索引)本身,否则二级索引不可能覆盖所有列,Extra一定不会是Using index - 查询中用了
DISTINCT、GROUP BY、ORDER BY非索引字段 → 即使SELECT字段全在索引里,也可能触发Using temporary或Using filesort,挤掉Using index - 索引字段含
NULL且查询条件为IS NOT NULL:InnoDB 对NULL的处理会让部分优化失效,Extra可能退化为Using where - MySQL 版本低于 5.6:不支持
Index Condition Pushdown,某些本该下推的条件被迫留在 server 层,导致Using where; Using index出现频率更高,甚至误判为“没走索引”
真正要盯的不是有没有 Using index,而是它出现时对应的 key_len 是否合理、rows 是否随数据增长线性上升、以及 filtered 是否稳定在 80 以上。这些比单看 Extra 更早暴露索引设计隐患。
本文共计950个文字,预计阅读时间需要4分钟。
Extra 列表中出现 Using index 是好事,但不等于没有索引问题——它只说明使用了覆盖索引,不代表查询设计合理、索引结构最优,更不意味着没有冗余字段或顺序缺失。
怎么一眼看出 Using index 是真覆盖还是假高效
覆盖索引的本质是:查询中 SELECT 的所有列 + WHERE 用到的所有列,全部落在同一个索引的最左前缀范围内。
常见误判点:
- 有
Using index,但WHERE条件用了函数(如WHERE YEAR(hire_time) = 2023)→ 实际走不了索引范围扫描,type可能是index或ALL,性能仍差 - 索引是
(name, age, position),但查询写成SELECT * FROM employees WHERE age = 25→ 不满足最左前缀,Extra不会显示Using index,哪怕age在索引里 -
SELECT中包含TEXT或BLOB字段 → 即使其他字段被索引覆盖,InnoDB 也无法把大字段存进二级索引页,Using index不会出现
Using index 和 Using where; Using index 的关键区别在哪
两者都表示走了覆盖索引,但过滤动作发生的层级不同,直接影响扫描行数和响应稳定性:
-
Using index:整个WHERE条件都能用索引精确匹配或范围扫描(比如WHERE name = 'Alice' AND age BETWEEN 20 AND 30),引擎层直接筛完,不回表也不在 server 层再过滤 -
Using where; Using index:索引覆盖了所有字段,但WHERE中有无法下推到引擎层的条件,例如LIKE '%suffix'、IS NULL、或者涉及隐式类型转换(如字符串字段查WHERE status = 1)→ 这些条件必须由 server 层对引擎返回的每一行再做一次判断 - 实际影响:
Using where; Using index的rows值往往偏高,因为引擎返回了更多中间结果;而filtered列如果远低于 100,就是 server 层过滤掉大量数据的信号
为什么有时加了索引却看不到 Using index
不是索引没生效,而是“覆盖”这个前提没达成。几个高频漏点:
-
SELECT *:除非是聚簇索引(主键索引)本身,否则二级索引不可能覆盖所有列,Extra一定不会是Using index - 查询中用了
DISTINCT、GROUP BY、ORDER BY非索引字段 → 即使SELECT字段全在索引里,也可能触发Using temporary或Using filesort,挤掉Using index - 索引字段含
NULL且查询条件为IS NOT NULL:InnoDB 对NULL的处理会让部分优化失效,Extra可能退化为Using where - MySQL 版本低于 5.6:不支持
Index Condition Pushdown,某些本该下推的条件被迫留在 server 层,导致Using where; Using index出现频率更高,甚至误判为“没走索引”
真正要盯的不是有没有 Using index,而是它出现时对应的 key_len 是否合理、rows 是否随数据增长线性上升、以及 filtered 是否稳定在 80 以上。这些比单看 Extra 更早暴露索引设计隐患。

