mysql如何通过执行流程分析慢SQL_性能排查思路说明

10次阅读

EXPLaiN关键字段需重点关注:type为ALL/index表示全表/全索引扫描,key为NULL说明未走索引,Extra含using filesort或Using temporary意味着排序/分组无法利用索引。

mysql如何通过执行流程分析慢SQL_性能排查思路说明

怎么看执行计划(EXPLAIN 输出关键字段)

mysqlEXPLAIN 是分析慢 SQL 最直接的入口,但很多人只看 typerows,漏掉真正致命的信号。重点盯住这几个字段:

  • type:出现 ALLindex 说明全表/全索引扫描,尤其 ALL 在大表上基本等于慢 SQL 定义;range 算可控,ref/eq_ref 才算走了有效索引
  • key:显示实际用到的索引名。为 NULL 就代表没走索引——别急着怪 SQL 写法,先确认该列是否真的有索引、索引顺序是否匹配 WHERE 条件
  • Extra:最危险的是 Using filesortUsing temporary,意味着排序或分组无法利用索引完成,必须额外内存或磁盘操作;Using index 是好现象(覆盖索引),Using index condition 表示用了 ICP(索引条件下推)

为什么加了索引还是没走(常见索引失效场景)

索引存在 ≠ 被使用。以下写法会让优化器主动放弃索引:

  • 对索引列做函数操作:WHERE YEAR(create_time) = 2024 → 改成 WHERE create_time >= '2024-01-01' AND create_time
  • 隐式类型转换user_idint,但写成 WHERE user_id = '123'字符串触发类型转换,索引失效
  • LIKE 左模糊:WHERE name LIKE '%abc' → 无法使用 B+Tree 索引的有序性;LIKE 'abc%' 可以
  • 联合索引顺序错位:INDEX(a,b,c),查询条件只有 WHERE b = 1WHERE b = 1 AND c = 2 → 无法命中该索引(最左前缀不满足)

如何模拟真实负载看执行流程(不只是单条 EXPLAIN)

EXPLAIN 只是预估,实际执行可能因数据分布、缓存、并发而不同。要验证真实行为,得结合:

  • 开启慢日志并设置合理阈值:SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1;,再查 slow_log 表或日志文件,确认是否真被记录
  • SHOW PROFILE 看各阶段耗时:
    SET profiling = 1; select ... ; -- 你的慢 SQL SHOW PROFILES; SHOW PROFILE FOR QUERY 1;

    重点关注 Sorting resultClosing tablesSending data 这些阶段是否异常高

  • 检查锁等待:SELECT * FROM performance_schema.events_statements_current WHERE SQL_TEXT LIKE '%你的SQL%'; 配合 sys.innodb_lock_waits 视图看是否卡在行锁上

ORDER BY 和 GROUP BY 怎么避免 filesort / temporary

这两个操作最容易触发临时表和文件排序,性能杀手。核心原则:让排序/分组字段落在同一个索引的后缀位置,并且顺序一致。

  • ORDER BY a, b → 索引要建为 INDEX(a, b),不能是 INDEX(b, a),也不能只建 INDEX(a)
  • GROUP BY a, b ORDER BY a, b → 同样需要 INDEX(a, b);如果还带 LIMIT,索引能极大提升效率
  • 注意 ASC/DESC 混用:ORDER BY a ASC, b DESC 在 MySQL 8.0 之前无法用单一索引优化(需分开建两个方向索引),8.0+ 支持 INDEX(a ASC, b DESC)
  • 如果业务允许,把 GROUP BY 提前聚合(比如用物化视图或定时汇总表),比实时计算安全得多

真实线上环境里,EXPLAIN 显示“走了索引”但响应仍慢,大概率是 rows 估算严重偏差(统计信息过期)、或者 Using filesort 占据了大部分时间——这两点最容易被忽略。

text=ZqhQzanResources