MySQL 慢查询优化:从定位到根治的完整思路

一、什么是慢查询?

慢查询通常指执行时间超过预期阈值的 SQL,比如:

  • 单次执行超过 1s
  • 在高并发场景下平均超过 100ms
  • 导致 CPU / IO 飙高、接口超时

在 MySQL 中,可以通过 慢查询日志​ 来捕获这些 SQL。

sql 复制代码
-- 查看是否开启
SHOW VARIABLES LIKE 'slow_query_log';

-- 设置阈值(单位:秒)
SET GLOBAL long_query_time = 1;

二、慢查询优化的标准流程(核心)

先定位 → 再分析 → 后优化 → 最后验证

1️⃣ 开启慢查询日志,找到"真凶"

不要凭感觉优化,要用数据说话:

  • 开启慢查询日志

  • 使用 mysqldumpslowpt-query-digest分析

  • 重点关注:

    • 执行次数多
    • 平均耗时高
    • 扫描行数大

2️⃣ 使用 EXPLAIN 分析执行计划

对可疑 SQL 执行:

ini 复制代码
EXPLAIN SELECT * FROM orders WHERE user_id = 123;

重点关注字段:

字段 关注点
type ALL(全表扫描)是大忌
key 实际使用的索引
rows 扫描行数,越小越好
Extra Using filesort / Using temporary 需警惕

目标

  • type 至少达到 range
  • key 不为 NULL
  • 避免 filesort 和临时表

3️⃣ 索引优化(最常见的手段)

✅ 建索引的原则

  • 高区分度字段(user_id、order_no)
  • WHERE / JOIN / ORDER BY 常用字段
  • 联合索引遵循最左前缀
  • 控制索引数量(写多读少表尤其注意)

❌ 常见索引失效写法

  • 对索引字段使用函数:DATE(create_time)
  • 隐式类型转换:phone = 13800000000
  • 左模糊:LIKE '%abc'
  • OR 条件中混合无索引字段
  • 不符合最左前缀

✅ 覆盖索引(进阶)

sql 复制代码
-- 索引 (user_id, status)
SELECT user_id, status FROM orders WHERE user_id = 123;

避免回表,显著提升性能。


4️⃣ SQL 改写优化

  • 避免 SELECT *
  • 大分页优化:
sql 复制代码
-- 避免
SELECT * FROM orders LIMIT 100000, 20;

-- 推荐
SELECT * FROM orders WHERE id > 100000 LIMIT 20;
  • 减少不必要的排序和分组
  • 拆分复杂 JOIN 和子查询

5️⃣ 表结构与业务层优化

  • 冷热数据分离(历史数据归档)
  • 读写分离(主写从读)
  • 适当冗余字段,减少 JOIN
  • 写多读少场景控制索引数量

三、加索引不是银弹(重要认知)

很多初学者容易陷入一个误区:

"查询慢?加索引!"

但现实情况是:

  • 索引会降低 INSERT / UPDATE / DELETE 性能
  • 索引占用磁盘空间
  • 索引过多会增加死锁概率
  • 返回大量数据时,索引效果有限

正确姿势

索引解决的是"扫描行数过多"的问题,不是所有慢查询的解药。


四、什么时候考虑分库分表?

当以下情况出现时,索引优化已接近极限:

  • 单表数据量超过千万级
  • 写入成为明显瓶颈
  • 硬件扩容成本过高

此时可以考虑:

  • 分库分表(ShardingSphere / MyCat)
  • 引入 ES / ClickHouse 处理复杂查询

⚠️ 注意

  • 分库分表会增加系统复杂度
  • 非分片键查询会退化为全表扫描
  • 应作为最后手段,而非首选方案

五、总结

慢查询优化不是一蹴而就的过程,而是一套组合拳:

慢查询日志定位 → EXPLAIN 分析 → 索引 + SQL 优化 → 表结构 / 架构调整

记住一句话:

索引是加速器,不是救命稻草;架构是解决扩展性问题的终极手段。


附:面试速记口诀

  • 慢查先看日志
  • EXPLAIN 看 type / key / rows
  • 索引失效避函数、避左模、避隐转
  • 覆盖索引少回表
  • 分页不用大 offset
  • 分表是最后一步

相关推荐
Nturmoils2 小时前
订单查询丢数据,查了半天原来是 WHERE 惹的祸
数据库·后端
叫我Paul就好2 小时前
自从用上 Agents View 之后, 我的心力交瘁感消失了
后端
SamDeepThinking2 小时前
组合还是继承?我在项目里主要看这两个判断
java·后端·面试
niuju2 小时前
一种基于 Agent 的需求规范化闭环实践:让合规与规范内建于流程
后端
团团崽_七分甜2 小时前
四大数据库底层原理详解
后端
glartchen2 小时前
使用 Pixi 配置 Whisper 环境,实现采用本地大模型读取视频字幕
后端
站大爷IP2 小时前
明明传了参数,进程池却说没找到?记一次变量丢失的排查实录
后端
用户6757049885023 小时前
从失真到绝对精准:Go语言中如何进行高精度计算?
后端·go
程序员cxuan4 小时前
GPT-5.6 官宣解禁,明天全量发布!
人工智能·后端·程序员