mysql数据库的查询优化器与执行计划分析

6次阅读

mysql执行计划用explain查看,关键看type、key、rows和extra;order by不走索引因不满足最左前缀、排序方向一致或范围条件中断;联合索引需按查询模式设计顺序;选错索引可强制指定、更新统计信息或排查隐式转换。

mysql数据库的查询优化器与执行计划分析

怎么看 MySQL 的执行计划(EXPLAIN)

直接在 select 语句前加 EXPLAIN,就能看到优化器打算怎么执行这条查询。它不真正运行查询,只返回执行计划的元信息。

关键字段要盯紧:type(访问类型)、key(实际用的索引)、rows(预估扫描行数)、Extra(额外操作,比如 using filesortUsing temporary)。

示例:

EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'paid';
  • typerefrange 好,range 又比 ALL(全表扫描)好
  • key 为空说明没走索引,得查原因:是不是索引失效?字段类型隐式转换?函数包裹了索引列?
  • rows 如果远大于实际结果集,往往意味着索引选择不当或统计信息过期,可运行 ANALYZE table orders;

为什么 ORDER BY 有时不走索引

MySQL 只有在满足“索引最左前缀 + 排序方向一致 + 无范围条件中断”的前提下,才能利用索引完成排序。一旦破坏任一条件,就会触发 Using filesort

常见断点场景:

  • WHERE 中用了范围查询(如 created_at > '2024-01-01'),后面跟的 ORDER BY id 就无法复用联合索引中的 id
  • ORDER BY a ASC, b DESC —— 多数版本不支持混合排序方向走索引(8.0.12+ 开始部分支持,但需显式定义降序索引)
  • SELECT * + ORDER BY indexed_col,但 WHERE 条件没覆盖该索引的最左列

验证方式:看 EXPLAIN 输出中 Extra 是否含 Using filesort;若存在,优先考虑调整索引顺序或拆分查询逻辑。

联合索引怎么建才不被“浪费”

联合索引不是字段简单砌,顺序决定它能覆盖哪些查询模式。优化器只会按索引定义的从左到右顺序匹配 WHERE 条件和 ORDER BY

建索引前先问三个问题:

  • 哪些字段最常出现在 WHERE 等值条件中?放最左
  • 是否有范围查询(>, BETWEEN, LIKE 'abc%')?它右边的字段就无法用于索引查找
  • 是否需要避免 filesort?把 ORDER BY 字段尽可能放在范围条件之后、索引末尾

例如,高频查询是:WHERE category = ? AND status IN (?, ?) ORDER BY created_at DESC,那么 (category, status, created_at) 是合理顺序;而 (status, category, created_at) 就会导致 category = ? 无法使用索引前缀。

查询优化器“选错索引”怎么办

优化器依赖表统计信息做成本估算,但数据分布倾斜、长期未更新统计、或复杂表达式都可能导致它误判。典型表现是明明有索引却走了全表扫描,或选了低效的索引。

可干预手段有限但实用:

  • 强制指定索引:SELECT * FROM t USE INDEX (idx_user_status) WHERE ...(慎用,后续数据增长可能让该索引再次变差)
  • 更新统计信息:ANALYZE TABLE t;,尤其在大批量导入/删除后
  • 检查是否因隐式类型转换导致索引失效:比如 user_idint,但传入字符串 '123',会触发全字段转类型,索引失效
  • SHOW WARNINGS 查看优化器重写后的语句,有时能发现意外的子查询展开或条件合并

真正棘手的是优化器在多个“看起来差不多”的索引间摇摆——这时候往往不是调优问题,而是数据模型或查询结构本身需要收敛,比如把大表关联拆成应用层分步查,或引入冗余排序字段减少动态计算。

text=ZqhQzanResources