上周整理服务器,顺手翻了一眼 MySQL 的慢日志,文件 916KB,里面攒了 1800 条记录,最早的一条是 2023 年 11 月,最新的是前天。站点本身没感觉慢,未缓存首页也就 0.7 秒上下,但这堆记录总得有个说法,不然下次真出问题又得从头猜。
翻完的结论有点反直觉:最慢的那条不在查表,在等锁;真正值得动手的是另一批老式查询,还有 wp_options 里一个 1.85MB 的自动加载项。
先看库有多大,哪张表最胖
WP-CLI 自带一个查表大小的子命令,不用连数据库:
wp db size --tables
Name Size
wp_options 4243456 B
wp_posts 3817472 B
wp_postmeta 704512 B
wp_usermeta 360448 B
整库 10.6MB,wp_options 和 wp_posts 占了八成,这个比例对 WordPress 来说正常。想看得再细一点,包括行数和碎片,可以问 information_schema:
wp db query "SELECT table_name, ROUND((data_length+index_length)/1024) kb, table_rows \
FROM information_schema.tables WHERE table_schema='littlesheep_cc' \
ORDER BY (data_length+index_length) DESC LIMIT 5"
wp_options 4144 kb 282
wp_posts 3728 kb 448
wp_postmeta 688 kb 2184
10MB 的库怎么都不会是瓶颈,内存里 256MB 的 buffer pool 能把整库装进去躺着。所以慢日志的问题不在容量,在别处。
慢日志里最慢的那条,在等锁
宝塔装的 MySQL 默认开了慢日志(/etc/my.cnf 里 slow_query_log=1),文件在 /www/server/data/mysql-slow.log,long_query_time=3,也就是超过 3 秒才记。日志格式固定,# Query_time 那一行同时带着 Lock_time:
awk '/^# Query_time:/ {qt=$3; lt=$5; getline; getline sql; \
printf "%9.2f %9.2f %s\n", qt, lt, substr(sql,1,55)}' \
/www/server/data/mysql-slow.log | sort -rn | head -8
5705.62 5695.03 SELECT option_name, option_value FROM wp_options WHERE
5705.34 5694.81 SELECT option_name, option_value FROM wp_options WHERE
3084.33 0.00 # administrator command: Quit;
1734.78 0.00 SELECT wp_posts.ID
860.43 0.00 SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
第一、二名都是 5705 秒,看着像一条 SQL 卡了 95 分钟。但 Lock_time 是 5694 秒,也就是说 99.8% 的时间在等表锁,不是在扫数据(Rows_examined 只有 203 行)。这两条的时间戳是 2023 年 12 月 22 日,那天正好是备份任务在跑,mysqldump 锁表期间所有查询排队的记录。
这类记录别当性能问题处理,该做的是把备份挪到凌晨并把锁方式改掉,我在全站自动备份那篇里写过怎么改。
真正属于「SQL 写得不好」的是另外一族,换个聚合方式就看到了:
awk '/^# Query_time:/ {qt=$3; re=$0; sub(/.*Rows_examined: /,"",re); \
getline; getline sql; if (sql ~ /SQL_CALC_FOUND_ROWS/) {n++; t+=qt; \
if(qt>m)m=qt; e+=re}} END {printf "n=%d avg=%.2fs max=%.2fs examined=%.0f\n", \
n, t/n, m, e/n}' /www/server/data/mysql-slow.log
n=609 avg=8.88s max=860.43s examined=558
609 条 SELECT SQL_CALC_FOUND_ROWS wp_posts.ID,平均 8.88 秒,平均扫 558 行。这是老式 WP_Query 分页查询的写法,先查一遍列表再算总数。我这边跑的是 WordPress 6.9,核心文件里还留着这个写法,多半是子比主题或者某个插件用自己的 SQL 在查列表,升级 WP 不会自动修掉它。查清是哪个插件之后,要么换更省的查询,要么给这张表补上合适的复合索引。
日志顺手提醒一句:里面混着 # administrator command: Quit;、SET timestamp=... 这种客户端输出,不是 SQL。聚合的时候先过滤掉,不然 top 榜会被噪声占掉半屏。
wp_options 里藏着一个 1.85MB 的备份
关键词是 autoload。WordPress 每次请求都会把所有 autoload 的 option 一次性读出来反序列化,所以这一栏越肥,每个页面都要多扛一份。
wp db query "SELECT option_name, ROUND(LENGTH(option_value)/1024) kb FROM wp_options \
WHERE autoload IN ('yes','on','auto','auto-on') ORDER BY LENGTH(option_value) DESC LIMIT 3"
zibll_options_backup 1849
zibll_options 123
ACG 16
zibll_options_backup 一行 1849KB,是子比主题保存的一份选项快照,等于每次打开页面都把整个主题配置备份读进来再丢掉。把它按未压缩 JSON 导出一份留底(我这边 1.66MB),然后关掉自动加载:
wp option get zibll_options_backup --format=json > /root/zibll-options-backup-20261013.json
wp option set-autoload zibll_options_backup off
wp db query "SELECT ROUND(SUM(LENGTH(option_value))/1024) kb FROM wp_options \
WHERE autoload IN ('yes','on','auto','auto-on')"
kb
216
自动加载总量从 2065KB 掉到 216KB,减掉的 1849KB 就是那一行。option 本身没删,需要它的代码照样按名字取,只是不再跟着每个请求预加载。
验证:两个数字的意思完全不一样
改完我想看首页快不快了,5 次未缓存请求(带随机参数绕开缓存)跑下来:改前 0.85/0.82/0.73/0.75/0.74 秒,改后 0.92/0.71/0.69/0.82/0.77 秒。两组数据完全重叠,看不出提升。
原因不复杂,这个表常驻 buffer pool,省下的是一次无意义的大 option 反序列化,不是省了磁盘 IO。真正吃掉那 0.7 秒的是 PHP 执行和主题模板。所以这次改动的收益是「少做一件没意义的事」,不是「网站变快了」,宣传成后者就是骗自己。
顺手跑了 wp db optimize,整库从 10.61MB 降到 9.36MB。输出里每张表都写着 Table does not support optimize, doing recreate + analyze instead——InnoDB 不认这条命令的默认语义,实际是重建表再分析统计信息,会短暂锁表,别在访问高峰做。
坑和回滚
回滚就一条命令,wp option set-autoload zibll_options_backup on,我试过,自动加载总量立刻回到 2065KB,站点全程 200。有个坑是官方文档和网上教程常写 auto,但 WP-CLI 只认 on/off/yes/no:
wp option set-autoload zibll_options_backup auto
Error: Invalid value specified for positional arg.
auto 是 WordPress 6.6 之后表里能存的值之一(同批还加了 auto-on,并且新写入超过 150KB 的 option 不再默认自动加载),但 WP-CLI 这个子命令的取值没跟着放开,手写 SQL 时别把两套搞混。老库里还留着一批 yes/no,含义等同于 on/off,统计时要一起算进去,只查 autoload='yes' 会漏。wp option set-autoload 从 WP-CLI 2.8.0 起才有,版本太老就先升 WP-CLI。
顺便说三件不用做的事
wp_postmeta 只有 2184 行,网上那些「给 meta_key 加索引提速」的文章可以关掉了,行数这么少加索引只会拖慢写入。孤儿 postmeta 查出 2 条,过期 transient 是 0 条——0 条的意思是别照抄清理脚本,先把数量查出来再决定。
数据库只是服务器上的一环,占磁盘的大头往往在别处,比如我上次查出来的那个 4.4G 的监控库文件;而数据库压力本身,我这边主要靠 Redis 对象缓存挡在前面,命中率上去之后 mysqld 的负载会明显降。
慢日志看久了会有点上瘾,但真正管用的动作就那么几个:分清等锁和慢查,认清哪些 SQL 是自己写坏的,再确认 autoload 里没躺着巨物。



![[教程][服务器]在阿里云服务器上卸载AliYunDunMonito(阿里盾)-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2025/12/114612929920251229005735.png)

![[免费][教程]子比主题美化,优化教程-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/09/3b06fd6a0520260920160148.webp)
![[免费][插件]将WordPress图片上传到LskyPro蓝空图床的插件-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/09/b9e1998d8420260920160152.webp)

![[教程][笔记]Centos7宝塔下安装ImageMagick,无法安装webp扩展解决办法-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/09/980f2f165520260920155616.webp)
![[资源][教程]AI SEO - WordPress插件-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/01/9f396016b220260112151830.png)



暂无评论内容