我是怎么做 mysql 调优的(实战思路)
这不是“某几个参数调一调”的问题,而是一整套从 架构 → sql → 索引 → 配置 → 系统 的排查流程。
你可以把这篇当成自己的 mysql 调优 checklist。
一、调优前的共识:先度量,再优化
调优最怕两件事:
- 拍脑袋调参数:改了一堆配置,qps 没上去,反而更慢;
- 只盯一个点:只会改
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:访问类型(all、index、range、ref、const等);all= 全表扫描,基本就是优化对象;
key:实际使用的索引;rows:预估扫描行数;extra:using filesort、using temporary、using 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 索引设计思路
- 区分“高频查询条件”和“偶尔查查”;
- 给经常出现在
where / join / order by / group by的列设计索引; - 尽量用 联合索引代替多个单列索引;
- 注意索引列的选择性(区分度):
- 性别、是否删除(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
- 用
iostat、vmstat、iotop看:- 磁盘队列长度、io 等待;
- 如果 io 明显成为瓶颈:
- 换 ssd;
- raid 级别调整;
- 分库分表、冷热分离。
5.2 cpu
- 大量复杂 sql、函数计算、排序、join 会吃 cpu;
- 通过慢查询 + explain 优化 sql,减少 cpu 压力;
- 必要时升级机器配置或做读写分离、分库。
5.3 网络
- 主从复制延迟大、跨机房访问慢;
- 尽量让数据库靠近应用部署(同一可用区/机房)。
六、第五刀:架构级优化(分库分表 & 读写分离)
当单实例再怎么调也扛不住时,就是架构层面问题了。
6.1 读写分离
典型做法:
- 主库负责写、从库负责读;
- 中间加一个数据访问层(或中间件)做路由;
- 部分请求强制走主库(写后立刻读)。
适合场景:
- 读远多于写;
- 允许短暂读到旧数据的场景。
6.2 分库分表
如果单表行数上亿,索引高度、统计信息、缓存命中都会出问题。
常见拆分维度:
- 按业务维度拆库(用户库、订单库、日志库);
- 按 hash/范围拆分大表:
- 用户 id 取模;
- 按时间分表(按月/按日)。
拆分后要注意:
- 跨分片 join 不再简单支持,需要应用层处理;
- 全局唯一主键(雪花算法、号段发号等);
- 分布式事务(能避则避,多用最终一致方案)。
七、监控与排查工具清单
调优离不开“观察工具”:
- 慢查询日志:慢 sql 排查入口;
explain/explain analyze:看执行计划、实际耗时;show processlist:看当前连接、是否有锁等待;show engine innodb status\g:看死锁、事务等待;information_schema/performance_schema/sys库:- 统计哪些 sql 最耗费资源。
- 操作系统工具:
top、iostat、vmstat、sar等。
八、一套实战调优流程(总结版)
给你一套可直接复用的步骤:
- 确认问题类型
- 慢:是个别 sql 慢,还是所有操作都慢?
- 卡:cpu 高?io 高?锁等待多?
- 开慢日志 + 抓 top sql
- 找出最慢/最频繁/总时长最高的 sql;
- 优先优化前 10% 的“重灾区”。
- 抓执行计划(explain)
- 看是否使用索引;
type是否为range/ref/const而不是all;- 是否大量
using filesort、using temporary。
- 设计/调整索引 & 改写 sql
- 减少全表扫描、回表、排序临时表;
- 利用覆盖索引和联合索引。
- 调整 innodb 核心参数
innodb_buffer_pool_size、innodb_log_file_size、innodb_flush_log_at_trx_commit等;- 压测不同参数组合的效果。
- 观察硬件资源
- 磁盘 io 是否打满;
- cpu 是否经常 100%;
- 内存是否频繁换页。
- 必要时考虑架构改造
- 加从库做读写分离;
- 对热点库/表做拆分。
九、小结
mysql 调优本质上是一个“找瓶颈 → 定位层级 → 有针对性优化”的过程:
- sql 与索引永远是第一优先级;
- innodb 参数是在“sql/索引合理之后”的加分项;
- 再往上,是硬件和架构层面的扩展。
一句话:
不要指望靠改几个参数就“神奇提速”,调优一定是数据驱动 + 全链路思考。
养成“看慢日志 + explain + 监控”的习惯,你的 mysql 水平会非常快地上来。
到此这篇关于mysql 调优的实战思路的文章就介绍到这了,更多相关mysql调优思路内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论