mysql如何查看SQL是否走索引_mysql执行计划分析方法

2次阅读

explain 是判断 mysql 是否使用索引最直接有效的方式,需重点观察 type、key、rows 和 extra 四列,并结合索引定义、隐式转换、函数使用等场景综合分析索引是否真正高效。

mysql如何查看SQL是否走索引_mysql执行计划分析方法

EXPLAIN 看执行计划,这是最直接有效的判断方式

MySQL 不会主动告诉你“用了哪个索引”,但 EXPLAIN 会把优化器的决策摊开给你看。在你要分析的 select 语句前加 EXPLAIN,比如:

EXPLAIN SELECT * FROM users WHERE email = 'a@b.com';

重点关注这四列:

  • type:值为 ALL → 全表扫描,没走索引;const/eq_ref/ref/range → 通常走了索引
  • key:非 NULL(如显示 idx_email)→ 实际使用了该索引
  • rows:预估扫描行数,远小于表总行数才说明索引过滤有效;接近总数可能已失效
  • Extra:出现 using filesortUsing temporary → 即使走了索引,排序或分组仍可能回表或额外开销

注意:key 非空 ≠ 高效,必须结合 typerows 综合判断。

常见索引失效场景,一查就中招

很多 SQL 表面看着合理,其实根本没走索引。典型例子包括:

  • 对索引列做隐式类型转换WHERE phone = 13800138000phoneVARCHAR),应写成 WHERE phone = '13800138000'
  • 在索引列上使用函数:WHERE YEAR(create_time) = 2023 → 改用范围查询:WHERE create_time >= '2023-01-01' AND create_time
  • 模糊查询以 % 开头:LIKE '%abc' → 无法利用索引,可考虑全文索引或倒排结构
  • 联合索引未满足最左前缀:INDEX(a, b, c),但只查 WHERE b = 1 → 不走索引;必须从 a 开始才有机会命中
  • 索引列参与计算:WHERE score + 10 > 90 → 改为 WHERE score > 80

辅助验证:查索引是否存在、是否被真正用过

光看 EXPLAIN 还不够,得确认基础条件是否成立:

  • SHOW INDEX FROM users; 查表上有没有对应索引,以及索引列顺序是否匹配查询条件
  • performance_schema.table_io_waits_summary_by_index_usage(MySQL 5.6+)看某索引实际被调用频次
  • 查询 sys.schema_unused_indexes(MySQL 5.7+ sys schema)识别长期零使用的冗余索引
  • 开启慢查询日志(slow_query_log=ON),设 long_query_time=1,捕获那些因未走索引而变慢的语句

这些不是替代 EXPLAIN 的手段,而是帮你定位“为什么明明建了索引却没被选中”。

进阶调试:用 OPTIMIZER_TRACE 看优化器怎么想的

EXPLAIN 显示没走索引,但你确信它“应该走”,就可以启用优化器跟踪:

SET optimizer_trace="enabled=on"; SELECT * FROM users WHERE age > 30; SELECT * FROM information_schema.optimizer_trace; SET optimizer_trace="enabled=off";

返回的 json 里会明确写出:“为什么放弃索引 idx_age?因为预估扫描行数占比太高,成本高于全表扫描”。这种细节,EXPLAIN 不会告诉你。

真正容易被忽略的是:索引是否“被选中”和是否“高效”是两回事——type=range + rows=10万 的查询,跟 type=ref + rows=2 的性能差距,可能比走不走索引还大。

text=ZqhQzanResources