mysql中EXPLAIN分析SQL查询性能的基本方法

3次阅读

type字段反映MySQL查找行的方式,从优到劣为system≈const>eq_ref>ref>range>index>ALL;ALL表示全表扫描,index需遍历整棵索引树,均需优化。

mysql中EXPLAIN分析SQL查询性能的基本方法

怎么看 EXPLaiN 输出里的 type 字段

type 表示 mysql 如何查找表中行,它直接反映连接效率。从好到差大致是:systemconst > eq_ref > ref > range > index > ALL。出现 ALL 意味着全表扫描,基本等于没走索引;index 是走索引但要遍历整个索引树,也不理想。

  • const:主键或唯一索引等值查询,只匹配一行,最快
  • ref:非唯一索引等值查询(比如 WHERE status = 'active'),可能返回多行
  • range:范围查询(BETWEEN>IN 等),注意 IN 里值太多会退化成 ALL
  • 如果 typeALLindex,优先检查是否缺失索引,或索引列顺序是否匹配 WHERE 条件

keypossible_keys 不一致说明什么

possible_keys 是 MySQL 认为能用上的索引列表,key 是最终选中的那个。两者不一致很常见,但需警惕以下情况:

  • possible_keys 有值,key 却是 NULL:说明优化器判断走索引比全表扫描还慢(比如表很小、或者索引选择性极差)
  • key 选了低效索引:比如你建了 (a, b) 联合索引,但查询只用了 b,MySQL 可能选错索引,这时加 FORCE INDEX 验证效果
  • 联合索引中,WHERE 条件跳过左列(如索引是 (user_id, created_at),但只查 created_at > '2024-01-01'),key 可能为空或降级为 index

Extra 里哪些值必须处理

Extra 是执行过程的补充信息,其中几个值几乎等于性能红灯:

  • using filesort:需要额外排序,没走索引排序。要么加覆盖索引(把 ORDER BY 字段包含进索引),要么确认是否真需要排序
  • Using temporary:创建临时表,常见于 GROUP BYDISTINCT 或复杂 JOIN。检查分组字段是否有索引,或能否改写避免临时表
  • Using index condition:正常,表示用了索引下推(ICP),是优化项,不是问题
  • Using where:说明存储引擎返回行后,Server 层还要再过滤——可能是索引没覆盖 WHERE 全部条件,也可能是用了函数/表达式导致索引失效(如 WHERE YEAR(created_at) = 2024

为什么加了索引 EXPLAIN 还不走

索引存在 ≠ 查询一定用。常见原因包括:

  • 查询条件对字段用了函数或计算,比如 WHERE UPPER(name) = 'JOHN'WHERE price + 10 > 100,会跳过索引
  • 隐式类型转换,比如 user_idint,但写成 WHERE user_id = '123'字符串),MySQL 可能放弃索引
  • 统计信息过期,执行 ANALYZE table table_name 更新后重看 EXPLAIN
  • 数据分布倾斜,比如某值占 95% 行数,优化器认为走索引更慢,可加 FORCE INDEX 强制验证实际耗时
EXPLAIN SELECT * FROM orders WHERE status = 'shipped' AND created_at > '2024-01-01';

真正卡点往往不在单个字段有没有索引,而在于联合索引的列顺序、查询条件是否满足最左前缀,以及 WHERE / ORDER BY / select 三者字段能否被同一个索引覆盖。别只盯着 key 是否非空,要通读 typekey_lenrowsExtra 四个字段组合起来看。

text=ZqhQzanResources