MySQL 调优别急着改参数,先把慢查询这条线捋直

2026-09-23 15:42 1004 次浏览

数据库开始变慢的时候,很多人的第一反应是打开配置文件改参数,把 innodb_buffer_pool_size 往上翻一倍,然后重启。结果重启那一分钟业务全断,起来之后查询该慢还是慢。我见过不少这样的操作,问题根本不在参数上。

调优这件事有先后顺序。顺序错了,花的时间全白费。下面按我平时排查的顺序说,从最省事的日志开始,一路到硬件。

先看慢查询日志,别凭感觉猜

MySQL 默认没开慢查询日志,很多人靠用户反馈「页面卡」来判断,这太粗。打开 slow_query_log,把 long_query_time 设成 1 秒,跑一天再看。通常真正拖慢系统的就那么几条 SQL,一页日志就能翻完。

看日志时重点盯两样:扫描行数和返回行数。如果一条查询扫了 200 万行只返回 10 行,那基本可以确定索引没建对。反过来,返回 5 万行的查询扫 5 万行,那是业务本身要这么多数据,加索引也没用,得改分页逻辑。

SHOW PROCESSLIST 也值得常看。压测时如果发现大量查询卡在 Sending data 状态,说明磁盘 IO 在扛大梁,这时候才轮到内存参数出场。

索引不是越多越好,写多读少的表尤其要克制

加索引能救读,但会拖慢写。一张每秒写入 3000 条的订单表,每多一个二级索引,插入时就要多维护一棵 B+ 树。我一般会先看这张表的读写比,读远大于写才敢放心加。

联合索引的顺序比数量重要。比如 WHERE user_id = ? AND status = ? ORDER BY created_at,索引建成 (user_id, status, created_at) 才能同时吃到过滤和排序。顺序换成 (status, user_id, created_at),当 status 区分度很低时,效果差一大截。

  • 区分度低的字段(比如性别、状态只有两三个值)不要单独建索引
  • 经常出现在 ORDER BY 里的字段,考虑放进联合索引尾部
  • 用 EXPLAIN 看 type 列,出现 ALL 或 index 就要警惕

还有一点,前缀索引在字符串字段上很实用。邮箱地址取前 10 个字符建索引,索引体积能小一半以上。

参数只动那几个真正影响大的

MySQL 有几百个参数,绝大多数不用碰。真正值得调的就那么几个,而且改之前要清楚代价。

innodb_buffer_pool_size 是最常被提的。它的作用是缓存数据和索引,设得太小,磁盘读会变多;设得太大,超过物理内存就会触发 swap,性能断崖式下跌。一般来说设成物理内存的 50% 到 70% 比较稳妥。一台 16G 内存的机器,配 10G 左右就够,别贪心设到 14G,操作系统自己也要留空间。

innodb_log_file_size 影响写性能。默认值偏小,写入频繁时会造成 checkpoint 频繁刷盘。调到 1G 到 2G 之间通常有帮助,但改这个参数要重启,而且改大了崩溃恢复时间会变长,这是取舍。

max_connections 不要盲目调大。每个连接都要占内存,设成 1000 而实际只用 100,多出来的连接会白白吃掉 buffer。连接池那边限好就够了。

换我我会先把慢查询和索引捋一遍,再考虑动参数。调参的收益通常排在索引之后。如果数据量涨到单机确实扛不住,比如磁盘 IO 长期跑满、内存加到头还是频繁读盘,那就不是调优能解决的了,得考虑换更宽的机器。像 马来西亚大带宽服务器 V 这种双路 E5-2683v4 配 64G 内存、300M 带宽的独立服务器,磁盘和内存都留了余量,适合数据量已经上来、单机参数调到头的情况。

调完之后怎么验证,别改完就完事

改完参数或加完索引,不要直接上生产。先在从库或者测试环境跑一遍同样的查询,对比执行时间和扫描行数。没有从库的话,至少挑业务低峰期观察一两个小时。

验证要看两个指标:QPS 有没有提升,以及 P99 延迟有没有下降。只看平均值容易被骗,一条慢查询就能把 P99 拉高,平均却看不出来。

如果调完发现没变化,别急着继续改。先想想是不是瓶颈根本不在数据库,有可能在应用层的连接池配置,也有可能网络往返本身就慢。我一般会先确认数据库这一层已经干净了,再往外找原因。

说到底,MySQL 调优的顺序是慢查询日志、索引、参数、硬件,一层一层往下。大多数业务量不大的站点,做完前两步就够用了,参数那步很多时候可以不动。真要动,一次只改一个,改完观察,别一口气改五六个,出了问题都不知道是哪个引起的。