mysql中使用EXPLAIN分析查询语句的索引效率

10次阅读

最关键看type、key、rows、Extra四个字段:type为ALL表示全表扫描;key为NULL说明未走索引;rows预估扫描行数,越大性能越差;Extra中using filesort或temporary需警惕。

mysql中使用EXPLAIN分析查询语句的索引效率

EXPLaiN 输出字段里哪些最关键

EXPLAIN 结果,别一上来就扫全列。重点关注这四个字段:typekeyrowsExtra

type 值从好到差一般是:consteq_ref > ref > range > index > ALL。出现 ALL 就是全表扫描,基本等于没走索引。

key 显示实际用到的索引名。如果为 NULL,说明没走索引;如果和你预期的不一样,得查是否索引失效或优化器选错了。

rowsmysql 预估需要扫描的行数,不是结果集行数。这个值越大,I/O 越高;比实际表行数还大,往往意味着索引没生效或条件写法有问题。

Extra 里要警惕:Using filesort(排序没走索引)、Using temporary(用了临时表)、Using index condition(ICP 开启,算好现象)、Using where; Using index(覆盖索引,理想状态)。

为什么加了索引却显示 type=ALL

常见原因不是索引没建,而是查询条件触发了索引失效。比如:

  • 对索引字段做函数操作:WHERE YEAR(create_time) = 2023 → 改成 WHERE create_time >= '2023-01-01' AND create_time
  • 隐式类型转换WHERE user_id = '123'(user_id 是 int)→ 字符串强制转数字,索引失效
  • LIKE 以通配符开头:WHERE name LIKE '%abc' → 无法用 B+ 树索引快速定位
  • 联合索引没用最左前缀:INDEX (a, b, c),但只查 WHERE b = 1 AND c = 2 → 不走索引

检查时先用 SHOW CREATE table 确认索引定义,再对照 WHERE 条件逐字核对是否满足最左匹配和无破坏性操作。

EXPLAIN format=jsON 能看出什么额外信息

默认的表格输出太简略。EXPLAIN FORMAT=json 会返回嵌套结构,揭示优化器真实决策路径。重点关注:

  • used_key_parts:实际用到的联合索引字段,比如 ["a","b"] 表示只用了前两列
  • filtered:表示该表条件过滤后剩余行数占比(百分比),值越低说明过滤效率越差
  • attached_condition:下推到存储引擎层的条件,和 Using index condition 对应
  • rows_examined_per_scan:单次扫描读取的行数,比普通 rows 更贴近真实 I/O

例如执行:

EXPLAIN FORMAT=JSON SELECT * FROM orders WHERE status = 'paid' AND amount > 100;

如果返回中 "used_key_parts": ["status"] 但没包含 amount,说明联合索引可能缺了第二列,或者 amount 的范围查询截断了索引使用。

ORDER BY 和 GROUP BY 容易被忽略的索引细节

很多人只关注 WHERE 是否走索引,但排序和分组同样依赖索引结构。关键点:

  • ORDER BY a, b 要高效,索引必须是 (a, b) 或更长前缀,且方向一致(不能 ORDER BY a ASC, b DESCINDEX (a ASC, b ASC)
  • GROUP BY 同理,如果没索引支持,就会触发 Using temporary; Using filesort
  • WHERE + ORDER BY 共存时,优先满足 WHERE 的最左前缀,再看能否覆盖 ORDER BY。比如 WHERE a = 1 ORDER BY b,索引 (a, b) 就比 (b, a) 合适得多
  • 注意 NULL 值处理:如果字段允许 NULL,而索引没特别设计,ORDER BY col DESC 可能无法利用索引(因 NULL 默认排在最前,与 DESC 冲突)

一个典型陷阱:select * FROM logs WHERE app = 'web' ORDER BY id DESC LIMIT 20。即使有 INDEX (app, id),若 id 是主键自增,MySQL 仍可能放弃该索引而走主键扫描——因为优化器认为按主键倒序取 20 行比用二级索引回表更便宜。这时得加 FORCE INDEX 或调整索引顺序验证。

text=ZqhQzanResources