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调优思路内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL进阶SELECT语法篇

    MySQL进阶SELECT语法篇

    从这个基本语法可以看出,最简单的SELECT语句是SELECT select_list,实际上利用这个最简单的SELECT语句,你也可以完成许多你期待的功能,首先你能利用它进行MySQL所支持的任何运算,例如:SELECT 1+1,它将返回2;其次,你也能利用它给变量赋值,而在PHP中,运用SELECT语句的这种功能,你就可以自由地运用MySQL的函数为PHP程序进行各种运算,并赋值给变量。在很多的时候,你会发现MySQL拥有许多比PHP更为功能强大的函数。
    2008-04-04
  • MySQL触发器Trigger加载及目前局限性

    MySQL触发器Trigger加载及目前局限性

    这篇文章主要为大家介绍了MySQL触发器Trigger加载以及目前局限性详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • MySQL数据表分区技术PARTITION详解

    MySQL数据表分区技术PARTITION详解

    在处理大规模数据时,数据库性能的优化变得尤为重要,MySQL提供了一种称为“分区”(Partitioning)的技术,可以显著提高查询效率和管理大型数据库表的能力,本文将详细介绍MySQL中的数据表分区技术,包括其基本概念、类型以及如何实现和维护,需要的朋友可以参考下
    2025-02-02
  • MySQL8中的存储引擎以及文件解析

    MySQL8中的存储引擎以及文件解析

    这篇文章主要介绍了MySQL8中的存储引擎以及文件使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • MySQL中DATE_FORMAT()函数将Date转为字符串

    MySQL中DATE_FORMAT()函数将Date转为字符串

    时间、字符串、时间戳之间的互相转换很常用,下面这篇文章主要给大家介绍了关于MySQL中DATE_FORMAT()函数将Date转为字符串的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 浅谈mysql使用limit分页优化方案的实现

    浅谈mysql使用limit分页优化方案的实现

    在mysql中limit可以实现快速分页,但是如果数据到了几百万时我们的limit必须优化才能有效的合理的实现分页了,否则可能卡死你的服务器哦。感兴趣的可以一起来了解一下如何实现优化
    2018-12-12
  • 一文搞懂Mysql的行级锁到底是怎么加的

    一文搞懂Mysql的行级锁到底是怎么加的

    在MySQL中行级锁是一种非常重要的锁机制,用于在高并发环境下提高数据库的性能和数据一致性,这篇文章主要介绍了Mysql的行级锁到底是怎么加的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2026-04-04
  • SQL算术运算符之加法、减法、乘法、除法和取模的用法例子

    SQL算术运算符之加法、减法、乘法、除法和取模的用法例子

    算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行加(+)、减(-)、乘(*)、除(/)和取模(%)运算,下面这篇文章主要给大家介绍了关于SQL算术运算符之加法、减法、乘法、除法和取模用法的相关资料,需要的朋友可以参考下
    2024-03-03
  • MySQL解决数据导入导出含有外键的方案

    MySQL解决数据导入导出含有外键的方案

    这篇文章主要介绍了MySQL解决数据导入导出含有外键的情况,文中通过图文结合的方式给大家讲解的非常详细,对大家解决问题有一定的帮助,需要的朋友可以参考下
    2024-11-11
  • MySQL之Innodb_buffer_pool_size设置方式

    MySQL之Innodb_buffer_pool_size设置方式

    这篇文章主要介绍了MySQL之Innodb_buffer_pool_size设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论