网站一到高峰期就卡,后台点一下要等三秒,刷新几次才出来,这类问题十有八九出在数据库。MySQL数据库优化不是把参数表从头到尾调一遍,而是按“先定位、再动手”的顺序来:先用慢查询日志捞出真正慢的语句,再看缺不缺索引,最后才轮到调参数。顺序反了,很容易调了半天没有效果。
一、先开慢查询日志,让数据库自己交底
慢查询日志是最诚实的排查入口,它把执行超过阈值的语句原样记下来,不用你靠猜。下面这段打开慢查询日志并把判定阈值设为 1 秒。要改的是 long_query_time 的数值(业务简单可以设 0.5 秒)和日志文件路径,注意该目录必须让 MySQL 运行账号有写权限,否则日志根本开不起来。跑完再查一次变量,确认状态是 ON。
-- 打开慢查询日志,超过 1 秒的语句都记下来
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 确认是否生效
SHOW VARIABLES LIKE 'slow_query_log';
观察一段时间后,用 mysqldumpslow 汇总日志,按耗时排序。下面这条命令取最耗时的前十条,排在第一的就是最该先处理的语句。看输出时重点看三列:执行次数、单次耗时、扫描行数,次数多又不快的查询优先级最高。
# 按执行时间汇总慢查询日志,取最耗时的前 10 条
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 或按出现次数排序,看被调用最多的慢语句
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
二、索引:加在该加的地方,别滥加
拿到慢 SQL,第一件事是看它缺不缺索引。把 EXPLAIN 加在那条语句前面,重点看 type 和 rows 两列:type 是 ALL 表示全表扫描,rows 是预估要扫的行数,数字越大越糟。该加索引的位置有规律可循:WHERE 条件里的字段、ORDER BY 排序的字段、JOIN 关联的字段。组合索引要记得最左前缀原则,例如 (user_id, created_at) 这个索引,单独用 created_at 查是用不上的。
-- 看执行计划:type 是 ALL、rows 很大就是要优化的信号
EXPLAIN SELECT id, title FROM article WHERE user_id = 100 ORDER BY created_at DESC LIMIT 20;
-- 给条件字段和排序字段建组合索引
ALTER TABLE article ADD INDEX idx_user_created (user_id, created_at);
索引不是越多越好。每加一个索引,写入和更新时都要多维护一份,表大了会明显拖慢插入。判断的标准是:这个字段真的被高频查询用到,且能过滤掉大部分数据。加完用 EXPLAIN 复测,type 从 ALL 变成 ref 或 range、rows 掉一个数量级,才说明加对了。
三、SQL 写法里的几个坑
有些慢不是索引的错,是写法的问题。常见的三类:一是 SELECT 星号把整行字段全拉回来,大字段尤其伤;二是在索引列上做运算或套函数,比如对时间字段用 DATE 函数判断,索引直接失效,要改成范围条件;三是循环里逐条查库,也就是常说的 N+1 查询,一次列表页发出几百条 SQL,得改成批量 IN 查询。还有深分页,limit 100000,20 会先扫掉十万行再丢掉,改成基于主键游标翻页能快出几个量级。
-- 反面写法:索引列上套函数,索引失效
SELECT id FROM article WHERE DATE(created_at) = '2026-09-01';
-- 正面写法:改成范围条件,索引可用
SELECT id FROM article
WHERE created_at >= '2026-09-01' AND created_at < '2026-09-02';
-- 深分页改成基于主键的游标翻页
SELECT id, title FROM article WHERE id > 100000 ORDER BY id LIMIT 20;
四、参数调优:先动内存,再动并发
SQL 和索引都理顺了,再谈参数。最值得动的是 InnoDB 缓冲池大小 innodb_buffer_pool_size,它缓存数据和索引,设成物理内存的六到七成通常合适,专用数据库机可以到八成,但别把系统内存吃干。max_connections 不要一看连接数不够就往上调,连接数放大后内存开销同步上涨,反而更容易触发内存不足。改完这些参数要重启 mysqld 才生效,一次只改一项并记录改动前后的表现。
-- 查看缓冲池配置与命中情况
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
-- 若 Innodb_buffer_pool_reads 持续增长,说明物理读多、缓存不够用
优化的闭环是:慢查询日志找出慢语句,EXPLAIN 判断病灶,加索引或改写写法,复测确认变快,最后才考虑参数。每一步都有数据可依,就不会陷入凭感觉乱调的循环。
相关阅读:
《数据库越来越慢拖垮整站?从慢查询日志开始查》
《网站内存占用高怎么办?定位吃内存进程与释放策略》
《网站加载速度优化都做了还是慢?瓶颈可能在服务端》
申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!
