mysql查询优化中的EXPLAIN分析与执行计划

3次阅读

EXPLAIN 重点关注 type、key、rows、Extra 四列:type 为 ALL 需优化,key 为空说明未用索引,rows 是预估扫描行数,Extra 含 Using filesort 或 temporary 是性能红灯。

mysql 查询优化中的 EXPLAIN 分析与执行计划

EXPLAIN 输出字段怎么看

执行 EXPLAIN SELECT …… 后,重点关注 typekeyrowsExtra 这四列。它们直接反映查询是否走索引、扫描范围多大、有没有临时表或文件排序。

  • type 值为 ALL 表示全表扫描,通常要优化;rangeref 是较健康的状态
  • key 为空说明没用上索引,即使有索引也可能因 隐式类型转换、函数包裹(如 WHERE YEAR(created_at) = 2023)而失效
  • rows 是 MySQL 预估的扫描行数,不是结果集大小;如果远大于实际返回行数,说明索引选择不佳或统计信息过期(可用 ANALYZE TABLE 更新)
  • Extra 出现 Using filesortUsing temporary 是性能红灯,尤其在大表分页(LIMIT 10000,20)时极易触发

联合索引顺序 为什么 不能乱

MySQL 的联合索引遵循最左前缀匹配原则,INDEX (a, b, c) 能命中 WHERE a = 1 AND b = 2,但对 WHERE b = 2 AND c = 3 完全无效。

  • 查询条件中跳过首字段(如只用 bc),索引就无法利用
  • 范围查询(>BETWEENLIKE 'abc%')之后的字段不再用于索引查找,例如 WHERE a = 1 AND b > 10 AND c = 5 中,c 不会走索引查找,仅用于过滤
  • 排序字段也要纳入联合索引覆盖,否则容易触发 Using filesort;比如 ORDER BY a, b,索引应建为 (a, b) 而非单独 (a)(b)

为什么有时候加了索引却没走

索引存在不等于被使用。MySQL 优化器会根据成本估算决定是否走索引,常见“有索引却不走”的原因包括:

  • 查询返回大量数据(如超过全表 20% 行数),优化器可能认为全表扫描比回表更快
  • 字段存在隐式类型转换:比如 user_idINT,但写成 WHERE user_id = '123',会触发字符串转数字,导致索引失效
  • 对索引字段使用函数或表达式:WHERE DATE(create_time) = '2024-01-01' → 改为 WHERE create_time >= '2024-01-01' AND create_time
  • 统计信息陈旧:执行 ANALYZE TABLE table_name 可强制更新,影响优化器决策

EXPLAIN FORMAT=JSON 有什么用

普通 EXPLAIN 只显示顶层执行计划,而 EXPLAIN FORMAT=JSON 提供嵌套结构,能看清子查询展开方式、索引合并(index_merge)、条件下推(attached_condition)等细节,适合复杂查询排障。

EXPLAIN FORMAT=JSON SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE status = 1);

输出中注意 "select_subquery""attached_condition" 字段,它们揭示子查询是否被重写为 JOIN、过滤条件是否下推到物化表——这些直接影响执行效率。很多看似“应该走索引”的慢查,真正瓶颈藏在 JSON 输出的 "filtered" 值里(表示该节点过滤后剩余行数比例),若长期低于 10%,说明条件区分度差,需要调整索引或查询逻辑。

text=ZqhQzanResources