MySQL 调优的实战思路

 更新时间:2025年12月13日 09:45:30   作者:CodeAmaz  
文章总结了MySQL调优的过程,包括从确认问题到解决的步骤,首先,需要度量问题,然后从SQL、索引、配置和系统等方面进行排查和优化,文章强调了SQL和索引的重要性,并提供了具体的优化方法,最后,文章提供了一个实战调优流程,以及一些监控和排查工具清单,感兴趣的朋友一起看看吧

我是怎么做 MySQL 调优的(实战思路)

这不是“某几个参数调一调”的问题,而是一整套从 架构 → SQL → 索引 → 配置 → 系统 的排查流程。
你可以把这篇当成自己的 MySQL 调优 Checklist。

一、调优前的共识:先度量,再优化

调优最怕两件事:

  1. 拍脑袋调参数:改了一堆配置,QPS 没上去,反而更慢;
  2. 只盯一个点:只会改 innodb_buffer_pool_size,其他全靠缘分。

所以第一步永远是:

  • 确认问题是什么
    • 慢?慢在哪?是“偶尔很慢”还是“永远都不快”?
    • CPU 打满?IO 打满?连接数飙高?锁等待多?
  • 收集基础信息
    • 版本:SELECT VERSION();
    • 业务类型:读多写少?写多读少?混合?
    • 数据量、QPS、TPS。
  • 看监控 / 日志
    • 慢查询日志(slow log);
    • CPU / IO / QPS 曲线;
    • SHOW GLOBAL STATUS 中的一些关键指标。

原则:先找到“最痛的那块”,再下手。

二、第一刀:从 SQL 入手(慢查询 & 执行计划)

绝大多数 MySQL 性能问题,都可以归结为:SQL 写得不行 + 索引没设计好

2.1 开启慢查询日志

SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;   -- 超过 1 秒的算慢查询
SET GLOBAL log_queries_not_using_indexes = 1;  -- 也可以先开一阵

然后看:

SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';

线下或运维平台中,可以用工具分析 slow log:

  • 比如 mysqldumpslow、pt-query-digest 等;
  • 找出 次数最多 / 最慢 / 总耗时最高 的那些 SQL。

2.2 对慢 SQL 用 EXPLAIN 做执行计划分析

EXPLAIN SELECT ...;

重点看:

  • type:访问类型(ALLindexrangerefconst 等);
    • ALL = 全表扫描,基本就是优化对象;
  • key:实际使用的索引;
  • rows:预估扫描行数;
  • ExtraUsing filesortUsing temporaryUsing index 等。

2.3 改写 SQL + 补索引

  • 常见优化方式:
    • 高频 WHERE 条件 / JOIN 字段 / ORDER BY 字段 建索引;
    • 把“函数/计算写在左边”的写法改掉:
-- ❌ 错误示例:索引容易失效
WHERE DATE(create_time) = '2025-01-01';
-- ✅ 正确示例:使用范围
WHERE create_time >= '2025-01-01 00:00:00'
  AND create_time <  '2025-01-02 00:00:00';

优先使用 联合索引 + 最左前缀

-- 经常这么查
WHERE user_id = ? AND status = ? AND create_time > ?;
-- 就建一个
CREATE INDEX idx_user_status_time ON t_order(user_id, status, create_time);
  • 避免在高并发场景下使用:
    • SELECT *(只取必要字段);
  • 大范围 IN
    • OR 拼字段(可考虑拆成 UNION);
    • 复杂嵌套子查询(可改 JOIN 或分步查询)。

实战经验:先搞定 Top N 慢 SQL,系统性能往往就上一个台阶。

三、第二刀:索引与表结构设计

3.1 索引设计思路

  1. 区分“高频查询条件”和“偶尔查查”;
  2. 给经常出现在 WHERE / JOIN / ORDER BY / GROUP BY 的列设计索引;
  3. 尽量用 联合索引代替多个单列索引
  4. 注意索引列的选择性(区分度):
    • 性别、是否删除(0/1)这类字段不要单独建索引
    • 可以放在联合索引里。

3.2 合理选择主键与存储引擎

InnoDB:

  • 强烈建议:自增整型主键 + InnoDB
  • 避免使用 UUID/业务字符串作为聚簇索引主键;
  • 避免过宽的主键,所有二级索引都要跟着变胖。

表结构方面:

  • 避免大字段(TEXT/BLOB)频繁参与查询,可拆分表;
  • 合理拆分“冷热字段”,避免每次查询都扫一大坨无关数据。

四、第三刀:InnoDB 关键参数调优

在 SQL & 索引搞定后,如果数据库仍吃紧,可以看配置。

4.1 innodb_buffer_pool_size(最关键的内存参数)

  • 作用:InnoDB 用来缓存数据页 + 索引页;
  • 一般建议:物理内存的 50%~70% 左右(线下压测决定);
  • 过小:大量读盘,性能抖;
  • 过大:挤压 OS 缓存/其他进程,可能换页。
innodb_buffer_pool_size = 8G   # 视机器内存而定

4.2 innodb_log_file_size / log_buffer_size

  • redo log 的大小和值:
    • 太小:频繁 flush,增加 IO;
    • 太大:崩溃恢复时间变长。
  • 典型值可从几百 MB 到几 GB,需结合写入量、硬件调整。
innodb_log_file_size = 1G
innodb_log_buffer_size = 64M

4.3 innodb_flush_log_at_trx_commit

控制事务提交时 redo log 的刷盘策略:

  • 1:每次事务提交都刷盘(最安全,最耗 IO);
  • 2:每次提交写 OS 缓存,每秒刷盘一次;
  • 0:每秒写一次 + 刷盘。

业务取舍:

  • 金融/强一致:倾向 1
  • 对少量数据丢失能接受,可以考虑 2,性能更好。

4.4 连接数相关

max_connections
thread_cache_size
wait_timeout
interactive_timeout
  • max_connections 不是越大越好:
    • 太大容易让机器被打爆;
    • 一般配合连接池使用,几百~一两千视情况。

五、第四刀:操作系统 & 硬件层面

当你确认:

  • SQL 已经相对合理;
  • 索引也设计得不错;
  • 配置也调过;

此时数据库仍然吃紧,就要看系统层面。

5.1 磁盘 IO

  • iostatvmstatiotop 看:
    • 磁盘队列长度、IO 等待;
  • 如果 IO 明显成为瓶颈:
    • 换 SSD;
    • RAID 级别调整;
    • 分库分表、冷热分离。

5.2 CPU

  • 大量复杂 SQL、函数计算、排序、JOIN 会吃 CPU;
  • 通过慢查询 + EXPLAIN 优化 SQL,减少 CPU 压力;
  • 必要时升级机器配置或做读写分离、分库。

5.3 网络

  • 主从复制延迟大、跨机房访问慢;
  • 尽量让数据库靠近应用部署(同一可用区/机房)。

六、第五刀:架构级优化(分库分表 & 读写分离)

当单实例再怎么调也扛不住时,就是架构层面问题了。

6.1 读写分离

典型做法:

  • 主库负责写、从库负责读;
  • 中间加一个数据访问层(或中间件)做路由;
  • 部分请求强制走主库(写后立刻读)。

适合场景:

  • 读远多于写;
  • 允许短暂读到旧数据的场景。

6.2 分库分表

如果单表行数上亿,索引高度、统计信息、缓存命中都会出问题。

常见拆分维度:

  • 按业务维度拆库(用户库、订单库、日志库);
  • 按 hash/范围拆分大表:
    • 用户 ID 取模;
    • 按时间分表(按月/按日)。

拆分后要注意:

  • 跨分片 JOIN 不再简单支持,需要应用层处理;
  • 全局唯一主键(雪花算法、号段发号等);
  • 分布式事务(能避则避,多用最终一致方案)。

七、监控与排查工具清单

调优离不开“观察工具”:

  1. 慢查询日志:慢 SQL 排查入口;
  2. EXPLAIN / EXPLAIN ANALYZE:看执行计划、实际耗时;
  3. SHOW PROCESSLIST:看当前连接、是否有锁等待;
  4. SHOW ENGINE INNODB STATUS\G:看死锁、事务等待;
  5. information_schema / performance_schema / sys 库:
    • 统计哪些 SQL 最耗费资源。
  6. 操作系统工具:topiostatvmstatsar 等。

八、一套实战调优流程(总结版)

给你一套可直接复用的步骤:

  • 确认问题类型
    • 慢:是个别 SQL 慢,还是所有操作都慢?
    • 卡:CPU 高?IO 高?锁等待多?
  • 开慢日志 + 抓 Top SQL
    • 找出最慢/最频繁/总时长最高的 SQL;
    • 优先优化前 10% 的“重灾区”。
  • 抓执行计划(EXPLAIN)
    • 看是否使用索引;
    • type 是否为 range/ref/const 而不是 ALL
    • 是否大量 Using filesortUsing temporary
  • 设计/调整索引 & 改写 SQL
    • 减少全表扫描、回表、排序临时表;
    • 利用覆盖索引和联合索引。
  • 调整 InnoDB 核心参数
    • innodb_buffer_pool_sizeinnodb_log_file_sizeinnodb_flush_log_at_trx_commit 等;
    • 压测不同参数组合的效果。
  • 观察硬件资源
    • 磁盘 IO 是否打满;
    • CPU 是否经常 100%;
    • 内存是否频繁换页。
  • 必要时考虑架构改造
    • 加从库做读写分离;
    • 对热点库/表做拆分。

九、小结

MySQL 调优本质上是一个“找瓶颈 → 定位层级 → 有针对性优化”的过程:

  1. SQL 与索引永远是第一优先级;
  2. InnoDB 参数是在“SQL/索引合理之后”的加分项;
  3. 再往上,是硬件和架构层面的扩展。

一句话:

不要指望靠改几个参数就“神奇提速”,调优一定是数据驱动 + 全链路思考
养成“看慢日志 + EXPLAIN + 监控”的习惯,你的 MySQL 水平会非常快地上来。

到此这篇关于MySQL 调优的实战思路的文章就介绍到这了,更多相关mysql调优思路内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 利用JuiceFS使MySQL 备份验证性能提升 10 倍

    利用JuiceFS使MySQL 备份验证性能提升 10 倍

    这篇文章主要介绍了如何让 MySQL 备份验证性能提升 10 倍,JuiceFS 非常适合用来做 MySQL 物理备份,通过不断调整 XtraBackup 的参数和 JuiceFS 的挂载参数,在一个小时内将时间缩短到原先的 1/10,下文一起来看相关内容的详细介绍吧
    2022-03-03
  • Mysql数据库手动及定时备份步骤

    Mysql数据库手动及定时备份步骤

    最近刚好用到了数据库备份,想着还有个别实习或者刚工作的小伙伴一个drop不小心删表、删库,心内慌得一批不知道该怎么办,就打算跑路了,学会这个小技巧就不用跑路了
    2021-11-11
  • MySQL InnoDB ReplicaSet(副本集)简单介绍

    MySQL InnoDB ReplicaSet(副本集)简单介绍

    这篇文章主要介绍了MySQL InnoDB ReplicaSet(副本集)的相关资料,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下
    2021-04-04
  • 浅析MySQL的lru链表

    浅析MySQL的lru链表

    这篇文章主要介绍了MySQL lru链表的相关资料,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-11-11
  • mysql 字符串长度计算实现代码(gb2312+utf8)

    mysql 字符串长度计算实现代码(gb2312+utf8)

    PHP对中文字符串的处理一直困扰于刚刚接触PHP开发的新手程序员。下面简要的剖析一下PHP对中文字符串长度的处
    2011-12-12
  • 简单解决Windows中MySQL的中文乱码与服务启动问题

    简单解决Windows中MySQL的中文乱码与服务启动问题

    这篇文章主要介绍了Windows中MySQL的中文乱码与服务启动问题,如果程序没有特殊需要则建议MySQL尽量默认设为UTF-8格式编码,需要的朋友可以参考下
    2016-03-03
  • MySQL 表分区步骤示例详解

    MySQL 表分区步骤示例详解

    MySQL表分区是一种数据库管理技术,用于将大型表拆分成更小、更可管理的分区(子表,这篇文章主要介绍了MySQL 表分区简介,需要的朋友可以参考下
    2023-09-09
  • mysql中engine=innodb和engine=myisam的区别介绍

    mysql中engine=innodb和engine=myisam的区别介绍

    MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持,本文为大家讲解下mysql中engine=innodb和engine=myisam的区别,不懂的朋友可以学习下,希望对大家有所帮助
    2013-07-07
  • MySQL数据库子查询语法规则详解

    MySQL数据库子查询语法规则详解

    子查询是在查询语句里面再嵌套一个查询,这是因为我们在提取数据的时候有很多不知道的数据产生了依赖关系。本文为大家总结了一下MySQL数据库子查询语法规则,感兴趣的可以了解一下
    2022-08-08
  • MySQL查看和修改最大连接数的方法步骤

    MySQL查看和修改最大连接数的方法步骤

    使用MySQL 数据库的站点,当访问连接数过多时,就会出现 "Too many connections" 的错误,所以我们需要设置MySQL查看和修改最大连接数,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10

最新评论