🪐前言
你有没有遇到过这种情况:WordPress 后台越来越慢,文章列表翻页要等好几秒,跑个备份脚本半天跑不完?打开 phpMyAdmin 一看,数据库体积几十甚至几百 MB——明明你的内容没那么多,怎么回事?
真相是:WordPress 在后台默默地、勤奋地、不知疲倦地攒垃圾。这篇文章不会跟你讲 MySQL 的理论和范式,而是直接带你找到垃圾在哪、怎么清、怎么让它以后不再长回来,以及看懂慢查询日志。

一、先看看你的数据库到底有多"胖"
动手之前,先搞清楚自己的数据库现状。你可以通过 phpMyAdmin、Adminer 或者主机面板的数据库管理工具来查。
🔍 快速诊断 SQL
登录 phpMyAdmin(通常是 cPanel → phpMyAdmin,或者直接 yoursite.com/phpMyAdmin),选中你的 WordPress 数据库,点 SQL 标签,跑这条查询:
-- 查看所有表的大小,按体积从大到小排序
SELECT
table_name AS `表名`,
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS `体积(MB)`
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY (data_length + index_length) DESC;
你会看到类似这样的输出:
| 表名 | 举例体积 |
|---|---|
| wp_posts | 48.2 MB |
| wp_postmeta | 32.7 MB |
| wp_options | 18.5 MB |
| wp_actionscheduler_actions | 12.1 MB |
| wp_comments | 3.8 MB |
如果你发现 wp_posts 和 wp_postmeta 这两张表加起来占了全库 60% 以上,那你遇到的正是最典型的数据库膨胀问题。原因就在下一节。
📊 解释一下你在看什么
- wp_posts:所有文章、页面、产品、媒体附件、修订版本、自动保存草稿、菜单项都存在同一张表里。不是只有你写的文章。
- wp_postmeta:每篇文章的附加数据——SEO 元数据、自定义字段、页面构建器的元素数据——一条一条存。一个 Elementor 页面可能产生几十甚至上百条 postmeta 记录。
- wp_options:WordPress 的设置、插件配置、瞬态缓存都在这里。装了又删的插件往往会留下孤立的 options 行。
二、清理垃圾数据:修订版本、自动保存、垃圾评论
现在你知道数据库为什么会膨胀了,本节逐一清理。
📝 修订版本是什么、为什么多
WordPress 默认每隔 60 秒自动保存一次你的编辑,而且每次你点"更新"按钮都产生一个修订版本。写一篇文章改了 30 遍,库里有 30 条历史版本。如果你写了一年博客,库里有几千条你永远不会再看的修订版本。
⚙️ WP-Optimize 一键清理(推荐)
装 WP-Optimize 插件(免费版就够用),进入 WP-Optimize → Database → Run Optimization:
// WP-Optimize 一键勾选清理项:
// 1. Clean all post revisions —— 清理所有修订版本
// 2. Clean all auto-draft posts —— 清理自动保存草稿
// 3. Remove spam comments —— 删除垃圾评论
// 4. Remove trashed comments —— 删除已回收的评论
// 5. Remove expired transient options —— 清理过期瞬态数据
// 6. Optimize database tables —— 优化数据表碎片
// 点 "Run all selected optimizations" 即可
// 耗时取决于数据库大小,通常 5-30 秒
WP-Optimize 还支持定时清理(设置 → 选频率),我一般设"每周一次",省得忘记。
🧹 如果你更相信自己动手——SQL 直接操作
有些朋友不信任插件,或者数据库已经卡到装插件都装不上。以下 SQL 在 phpMyAdmin 里直接跑,效果和 WP-Optimize 一模一样。
-- 1. 删除所有文章修订版本
DELETE FROM wp_posts WHERE post_type = 'revision';
-- 2. 删除所有自动保存草稿
DELETE FROM wp_posts WHERE post_status = 'auto-draft';
-- 3. 删除垃圾评论和已删除评论
DELETE FROM wp_comments WHERE comment_approved IN ('spam', 'trash');
-- 4. 清理孤立的 postmeta 记录(文章已删除但 meta 残留)
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;
-- 5. 清理过期瞬态数据
DELETE FROM wp_options WHERE option_name LIKE '_transient_timeout_%';
DELETE FROM wp_options WHERE option_name LIKE '_transient_%';
⚠️ 跑 SQL 之前一定先备份数据库。 到 phpMyAdmin → Export → Quick → Go 导出一份 .sql 文件存在本地。这句不是废话,我见过有人删
wp_postmeta时误删了正常数据的。
🚫 从源头遏制垃圾:限制修订版本数量
清理只是治标,要治本得限制 WordPress 产生垃圾的速度。在 wp-config.php 里加一行:
// 限制每篇文章最多保留 3 个修订版本
define('WP_POST_REVISIONS', 3);
// 如果你确定不需要修订功能,直接禁用
// define('WP_POST_REVISIONS', false);
同时把自动保存间隔拉长(默认 60 秒太频繁了):
// 自动保存间隔改为 300 秒(5 分钟)
define('AUTOSAVE_INTERVAL', 300);
这两行改完,以后你的数据库不会再像之前那样疯长了。

三、数据表优化与索引原理
数据表优化和索引是两个不同层面的操作,我分开讲。
🧽 数据表碎片整理(OPTIMIZE TABLE)
MySQL 在频繁的 INSERT / UPDATE / DELETE 操作后会产生"碎片"——数据存储在磁盘上不是连续排列的,有空洞。碎片多了,查询时磁盘要多跑好几趟,速度就慢。
清理碎片用 OPTIMIZE TABLE 命令:
-- 对单张表优化
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;
-- 一次性优化所有表(生成全部 OPTIMIZE 命令再逐条执行)
-- 在 phpMyAdmin 里:选中所有表 → 从下拉菜单选"优化表"
WP-Optimize 插件里也有这个功能(上节第 6 项),效果一样。
什么时候该跑 OPTIMIZE:我建议每次大规模清理修订版本之后跑一次,以及每个月定期跑一次。
🔑 数据库索引的底层直觉
不需要你懂 B-Tree 和哈希索引的原理。你只需要知道:索引就像一本书前面的目录——没索引,MySQL 要从头到尾扫整张表(全表扫描);有索引,MySQL 直接翻到对应页码。
WordPress 核心表已经建了大部分必要的索引,你一般不需要手动加。但有一个常见的索引缺失场景:插件创建的自定义表往往不加索引。
检查方法:在 phpMyAdmin 里点一张表 → Structure 标签 → 看 Indexes 区域。
-- 查看某张表的索引情况
SHOW INDEX FROM wp_postmeta;
-- 如果某列经常被查询但没索引,比如 WooCommerce 订单表的 _order_key
-- 可以这样加索引(谨慎操作,先备份)
-- ALTER TABLE wp_wc_orders ADD INDEX idx_order_key (order_key);
⚠️ 加索引不是免费的。索引加速了查询,但减慢了写入(INSERT/UPDATE/DELETE 时索引也要同步更新)。一般 WordPress 站不需要手建索引——除非你明确发现某条查询跑到秒级,且 EXPLAIN 显示全表扫描。
四、phpMyAdmin 慢查询日志排查
如果你的数据库清理和优化做完之后,速度问题还没彻底解决,下一步就是抓出到底是哪条 SQL 拖后腿。
📋 开启慢查询日志
慢查询日志默认可能是关闭的。在 phpMyAdmin 里跑这条查一下状态:
-- 查看慢查询日志是否开启
SHOW VARIABLES LIKE 'slow_query_log%';
-- 查看当前慢查询阈值(记录执行时间超过这个值的查询)
SHOW VARIABLES LIKE 'long_query_time';
如果 slow_query_log 显示 OFF,而你用的是共享主机,你大概率没有权限开启——这时候联系主机商,请客服帮开,通常他们会配合。
如果你是 VPS/独立服务器,SSH 进去在 MySQL 配置里改:
# 编辑 MySQL 配置文件(路径因系统而异)
sudo nano /etc/mysql/my.cnf
# 在 [mysqld] 段添加或取消注释
# slow_query_log = 1
# slow_query_log_file = /var/log/mysql/slow-query.log
# long_query_time = 1
# log_queries_not_using_indexes = 1
# 重启 MySQL
sudo systemctl restart mysql
🔬 看懂慢查询日志
日志文件里每条慢查询都有三部分关键信息:
# Time: 2026-05-09T14:32:18.508223Z
# User@Host: wpuser[wpuser] @ localhost []
# Query_time: 2.148723 Lock_time: 0.000142 Rows_sent: 10 Rows_examined: 89124
SELECT post_title FROM wp_posts WHERE post_status = 'publish' AND post_type = 'product' ... ;
关键字段解读:
- Query_time:这条查询跑了多久。2.14 秒,就这一条查询拖慢了整个页面
- Lock_time:等待锁的时间。如果这个值很高,说明有表被长时间占用
- Rows_examined:MySQL 为了执行这条查询检查了多少行。89124 行才返回 10 条结果——典型缺乏索引的信号
- Rows_sent:最终返回了多少行
如果 Rows_examined 远大于 Rows_sent(比如 10 万 vs 10),且 Query_time 超过 1 秒——这就是你要优化的查询。
🎯 针对慢查询的对策
找到慢查询之后,最实用的三步:
// 1. 把这句 SQL 放到 phpMyAdmin 里,前面加 EXPLAIN,看执行计划
// 2. 找到 type 列是 ALL(全表扫描)或 rows 特别大的行——这些是需要加索引的列
// 3. 如果慢查询来自某个插件,去插件设置里找相关功能——可能是某个后台定时任务(cron)在跑,
// 比如 WooCommerce 的报告生成、分析统计表更新等,把频率调低或改用 CLI 方式执行
-- 分析慢查询的执行计划
EXPLAIN SELECT post_title FROM wp_posts WHERE post_status = 'publish' AND post_type = 'product';
| 指标 | 含义 | 理想值 |
|---|---|---|
| type | 连接类型 | ref / eq_ref / const(ALL 是坏的,代表全表扫描) |
| rows | 预估扫描行数 | 越小越好 |
| key | 实际使用的索引 | 不能是 NULL |
| Extra | 额外信息 | 避免 Using filesort / Using temporary |

五、优化前后体积对比:一张表看效果
以下是一个运营了两年的外贸 B2B 站的真实数据:
| 优化项 | 优化前 | 优化后 | 清理量 |
|---|---|---|---|
| 数据库总体积 | 232.6 MB | 61.4 MB | -73.6% |
| wp_posts(含修订版本清理) | 78.3 MB | 21.7 MB | -72.3% |
| 修订版本条数 | 8,472 条 | 0 条 | 全部清除 |
| 自动保存草稿 | 1,356 条 | 0 条 | 全部清除 |
| wp_postmeta(孤立记录清理) | 56.1 MB | 22.8 MB | -59.4% |
| 垃圾评论 | 3,241 条 | 0 条 | 全部清除 |
| 过期瞬态数据 | 12,400+ 行 | 0 行 | 全部清除 |
| 数据表碎片整理 | 碎片率 19% | 碎片率 < 1% | OPTIMIZE 回收 |
优化手段:WP-Optimize 一键清理 + SQL 删除孤立 postmeta + OPTIMIZE TABLE 碎片整理 + wp-config.php 限制修订版本数量。

六、数据库维护的长期 SOP
别等数据库再次膨胀到上百 MB 才动手。建立一个简单的维护节奏:
- 每周:WP-Optimize 定时清理(设为自动)
- 每月:跑一次
OPTIMIZE TABLE(WP-Optimize 定时任务可包含) - 每季度:phpMyAdmin 导出一份完整备份到本地,顺便检查慢查询日志
- 每次卸载插件后:手动检查
wp_options表是否留下插件的残留项
总结
数据库优化是 WordPress 运维里最被低估的一环。回头看核心操作其实就四件事:
- 🗑️ 定期清理修订版本、自动保存、垃圾评论、过期瞬态——WP-Optimize 一键搞定
- 🧽 碎片整理——
OPTIMIZE TABLE回收磁盘空间,提升查询效率 - 🚫 源头控制——
wp-config.php限制修订版本数量,拉长自动保存间隔 - 🔍 慢查询排查——用慢查询日志 +
EXPLAIN找出拖后腿的 SQL,定位是缺索引还是插件定时任务负载过高
🆘 求助路径
- phpMyAdmin 官方文档:docs.phpmyadmin.net —— SQL 查询和数据库管理操作
- WordPress 数据库描述:developer.wordpress.org/reference/classes/wpdb/ —— 核心表结构和函数
- MySQL 官方手册:dev.mysql.com/doc/ —— 慢查询日志和 SQL 优化指南
- WP-Optimize 支持:wordpress.org/support/plugin/wp-optimize/ —— 插件问题
- 主机商客服:慢查询日志无权限开启时,联系主机商协助



删 revision 前真的先备份,别手快
AUTOSAVE_INTERVAL 改 300 这个我先试试
wp_options 残留插件名要怎么查?
Rows_examined 十万查十条,看到这个有点慌
吃瓜,原来后台慢不全是主机锅