如何判断查询是否走索引(type / key / rows / Extra)

9次阅读

EXPLaiN 的 type 值反映索引使用质量,理想为 ref 或 range;ALL 和 index 表示未有效过滤,需检查索引设计、WHERE 条件是否符合最左前缀原则及是否存在函数/类型转换等导致索引失效的因素。

如何判断查询是否走索引(type / key / rows / Extra)

怎么看 EXPLAIN 里的 type 值是否合理

type 表示 mysql 如何查找行,它直接反映索引使用质量。值从好到差大致是:systemconst > eq_ref > ref > range > index > ALL

重点盯住 ALLindex:前者全表扫描,后者虽走索引但仍是全索引扫描(等价于没过滤),都意味着查询没真正利用索引的筛选能力。

  • refrange 通常是健康信号,说明用了索引做等值或范围查找
  • eq_ref 多见于主键/唯一索引关联,效率最高
  • 如果本该走 ref 却显示 ALL,先检查 WHERE 条件列是否在索引最左前缀上
  • typeindexrows 很大,大概率是只用索引做覆盖扫描,没用于过滤——得看 keyExtra 配合判断

key 显示 NULL 或非预期索引名的原因

key 字段明确告诉你优化器实际选了哪个索引。它为 NULL 意味着完全没走索引;显示一个你没想用的索引,则说明优化器认为它更优(或你的目标索引不可用)。

  • 常见原因包括:WHERE 中用了函数(如 YEAR(created_at))、隐式类型转换(如字符串字段查数字)、OR 条件中部分分支无法用索引
  • 复合索引只对最左前缀生效:INDEX(a, b, c) 支持 aa,ba,b,c 查询,但不支持单独 bb,c
  • 如果强制指定索引(USE INDEX)后 key 变了但性能更差,说明优化器原本的选择未必错——别盲目干预

rows 数值远大于实际结果集说明什么

rows 是优化器预估的扫描行数,不是返回行数。它偏大通常意味着索引选择不当或统计信息过期。

  • rows = 100000select count(*) 实际只有 200 行,优先执行 ANALYZE table table_name 更新统计信息
  • rowsEXPLAIN format=jsON 中的 filtered 值相乘,约等于最终输出行数。比如 rows=10000filtered=10.00,说明大约返回 1000 行
  • 复合索引中,如果 WHERE 只用了右半部分(如 INDEX(a,b) 中只查 b = ?),rows 会接近全表,因为索引无法跳过 a

Extra 里哪些提示真危险

Extra 是关键线索,尤其几个带“using”的提示:

  • Using filesort:需要额外排序,没走索引排序。即使 ORDER BY 字段有索引,也要求顺序和索引顺序一致且无范围条件干扰
  • Using temporary:创建临时表,常见于 GROUP BY + 非索引字段、DISTINCTunion。和 Using filesort 同时出现,基本可判定性能瓶颈
  • Using index:好事,表示走了覆盖索引(只查索引就拿到所有字段),不用回表
  • Using where; Using index:更好,既覆盖又做了索引层过滤
  • Using index condition:启用了 ICP(索引条件下推),说明部分 WHERE 条件下推到存储引擎层执行,减少回表次数

真正要警惕的是 Using filesortUsing temporary 共存,这时加索引往往治标不治本,得重审查询逻辑或考虑物化中间结果。

text=ZqhQzanResources