SQL EXPLAIN 执行计划分析与优化方法

7次阅读

SQL EXPLAIN 执行计划分析与优化方法

EXPLaiN 是分析 sql 执行效率最直接的工具,它不真正执行语句,而是返回数据库优化器预估的执行路径。关键不是看“有没有用上索引”,而是理解 数据如何被检索、连接、过滤和排序,再结合实际数据分布与索引结构做针对性调整。

读懂 EXPLAIN 输出的核心字段

mysql 为例,重点关注以下几列:

  • type:连接类型,从好到差大致为 const ≈ eq_ref > ref > range > index > ALL。出现 ALL(全表扫描)或 index(全索引扫描)需警惕,尤其在大表上
  • key:实际使用的索引名。为 NULL 表示未走索引,可能因条件不匹配、隐式类型转换、函数包裹字段等导致
  • rows:优化器预估需要扫描的行数。该值远大于实际返回结果行数(如查 10 行却扫 10 万行),说明筛选效率低,索引选择或条件写法可能有问题
  • Extra:常见不利提示包括 using filesort(需额外排序)、Using temporary(建临时表)、Using join buffer(块嵌套连接回退)——这些往往意味着缺失合适的联合索引或排序字段未被索引覆盖

常见低效模式与对应优化方向

很多性能问题有典型诱因,可快速定位:

  • WHERE 条件中对索引字段使用函数或运算:例如 WHERE YEAR(create_time) = 2024 会让索引失效。应改写为范围查询:WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'
  • LIKE 左模糊WHERE name LIKE '%abc' 无法利用索引。若业务允许,尽量改为右模糊 LIKE 'abc%';否则考虑全文索引或倒排表
  • OR 连接多个非索引字段:如 WHERE a = 1 OR b = 2,且 a、b 单独有索引但无联合索引,可能导致全表扫描。可拆成 union 查询,或建立 (a,b) 覆盖索引(视查询需求而定)
  • ORDER BY 与 WHERE 不共用索引:例如 WHERE status = 1 ORDER BY created_at,若只有 status 索引,排序将触发 Using filesort。应建立联合索引 (status, created_at)

联合索引设计与最左前缀原则验证

联合索引不是简单把字段在一起,必须符合查询条件的实际使用顺序:

  • 索引 (a, b, c) 可用于 WHERE a = ?WHERE a = ? AND b = ?WHERE a = ? AND b = ? AND c = ?,也可用于 WHERE a = ? ORDER BY b
  • 但不能用于 WHERE b = ?WHERE b = ? AND c = ?(跳过最左列),也不能高效支持 WHERE a = ? ORDER BY c(中间断开)
  • 用 EXPLAIN 验证:添加索引后再次执行,观察 key 是否命中、rows 是否显著下降、Extra 是否消失 Using filesortUsing temporary

执行计划并非绝对,需结合真实数据验证

EXPLAIN 显示的是优化器“预测”,实际性能受数据倾斜、统计信息陈旧、缓存状态等影响:

  • 执行 ANALYZE table table_name 更新表统计信息,避免优化器误判
  • select ... INTO DUMPFILE 或慢日志中的 Query_timeRows_examined 对比 EXPLAIN 的预估值
  • 对复杂查询,可分步 EXPLAIN 子查询或临时表,避免被外层操作掩盖内层瓶颈
text=ZqhQzanResources