MySQL 慢查询完整排查

1、开启慢查询日志(抓慢 SQL)

  1. slow_query_log=ON 开启慢查询日志
  2. long_query_time:慢查询阈值,单位秒
    • 普通业务:1~2s
    • 金融交易、高并发核心链路:500ms(0.5)
  3. slow_query_log_file:慢日志文件路径
  4. log_queries_not_using_indexes:记录没有使用索引的 SQL(测试环境开启,生产谨慎,压力大)

注意:long_query_time统计的是SQL 实际执行时间,不包含锁等待时间;如果 SQL 因为锁等待卡住,不会被慢日志捕获。

工具:mysqldumpslow 分析慢日志,汇总相同 SQL 的执行次数、平均耗时。

2、explain 执行计划重点字段(面试高频)

重点看:type、key、rows、ref、Extra

type 访问类型(优先级从差到优)

ALL > index > range > ref > eq_ref > const/system

  1. ALL:全表扫描,性能最差,必须优化,没有可用索引
  2. index:扫描整个索引树,比 all 好,但依然大量 IO
  3. range :范围查询,> < >= <= in between,用到索引范围扫描
  4. ref:非唯一索引等值匹配,命中多行
  5. eq_ref:唯一索引等值,最多匹配一行(主键 / 唯一索引关联)
  6. const:常量匹配,主键 / 唯一索引直接定位一行

生产目标:type 尽量达到ref/range,禁止大量 SQL 出现ALL

key

  • key:实际真正使用到的索引,null 代表没走索引
  • possible_key:理论上可以选用的索引,不一定真正用到

rows

MySQL 预估需要扫描的行数,数值越大性能越差,是预估值,不是真实返回行数。

ref

索引匹配时使用的列 / 常量,显示索引列匹配的是常量还是其他表字段。

Extra 额外信息,重点坑点

  1. Using index ✅ 覆盖索引,不需要回表,性能优秀
  2. Using temporary ❌ 创建临时表,常见于group by、distinct、union,消耗内存 / 磁盘,性能差
  3. Using filesort ❌ 文件排序,不是磁盘文件,是内存排序,order by 无法利用索引排序,需要额外排序,大结果集非常慢
  4. Using where:存储引擎返回数据后,server 层再过滤条件
  5. Using join buffer:关联查询没用到索引,使用连接缓冲区

只要出现 Using temporary / Using filesort 就要重点优化。

3、四大层面优化手段

① 索引层面(最常用)

  1. 给 where、join、order by、group by 字段建立合适索引
  2. 遵循最左前缀原则,联合索引顺序:等值条件 > 范围条件 > 排序分组字段
  3. 避免索引失效:
    • 不要对索引列做函数运算、隐式类型转换
    • like %xxx 前缀模糊查询不走 B + 树索引
    • or 左右两边字段都要建索引,否则索引失效
  4. 使用覆盖索引,减少回表
  5. 删除冗余、重复、很少使用的索引,索引不是越多越好,会加重写操作负担

② SQL 语句书写层面

  1. 避免 select *,只查需要的字段,利于覆盖索引
  2. 大表禁止select count(*)统计全量;limit 大偏移量分页优化(延迟关联)
  3. 减少 in 里面大量集合元素,大 in 可以改成 join
  4. 避免order by rand()
  5. group by 尽量利用索引,避免 Using temporary;filesort
  6. 拆分大 SQL,不要一次性查询超大结果集;避免一次性查出几万行以上数据到应用内存
  7. 少用子查询,优先 join;避免 not in,改用 not exists 或者 left join

③ 架构层面

  1. 读写分离:读压力大,主写从读,分担查询压力
  2. 分库分表:单表数据量千万级别以上,水平拆分,降低单表扫描行数
  3. 引入缓存 Redis,热点查询直接缓存,绕过 MySQL 查询
  4. 业务层限制查询,分页做上限,禁止无边界查询

④ 数据库设计 & 配置层面

数据库设计

  1. 合理字段类型,尽量小,避免大 text/blob 字段;大字段单独拆分出去
  2. 范式适度,适当反范式,减少多表 join
  3. 避免大事务,事务时间过长会锁等待、MVCC 开销

配置参数

  1. join_buffer_size、sort_buffer_size、tmp_table_size,不要调太大,每个连接都会分配内存
  2. innodb_buffer_pool_size:核心,缓存索引和数据页,一般设置机器内存 50%~70%
  3. 慢查询阈值根据业务调整,核心链路调小
  4. 锁相关:排查行锁表锁,长事务导致锁等待引发慢查询

4、补充容易踩坑点

  1. explain 只是预估执行计划,不一定完全等于真实运行;MySQL 优化器会根据数据量选择索引,统计信息不准会选错索引,可以 analyze table 更新统计信息。
  2. 慢查询日志抓不到锁等待耗时;锁等待问题要看 show engine innodb status、performance_schema。
  3. 索引优化不是万能,写多的业务,索引越多插入更新越慢。
相关推荐
2603_954708313 分钟前
微能网协调控制箱突破传统微电网架构瓶颈
大数据·数据库·人工智能·架构·能源
l1t7 分钟前
一个clickhouse易错的语法问题
数据库·sql·clickhouse
Source.Liu8 分钟前
【A11】服务器底层权限表笔记
运维·服务器·笔记
啵啵啵鱼9 分钟前
六、联合查询
数据库·oracle
蓝胖的四次元口袋9 分钟前
Redis 知识梳理(4)
数据库·redis
先知后行。15 分钟前
gdb、asan、Valgrind
linux·运维·服务器
Light6018 分钟前
企业自建 AI 智能体,成本差 8 倍还是 46 倍?
java·人工智能·算法·知识图谱·rag·ai agent 上下文·token 成本
Wang's Blog26 分钟前
Java 项目实战: 交友项目 - 阿里云 OSS 对象存储介绍
java·阿里云·交友
yyuuuzz26 分钟前
云服务器部署 web 项目的进程常驻记录
运维·服务器·前端·阿里云·云计算·aws