本文约 3,249 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言
WordPress 用久了,很多人会发现网站越来越慢,后台打开要转半天,数据库文件也从几十兆涨到了几个 G。查一下才发现,真正属于你文章的数据没多少,大量空间被”垃圾”占了:每次编辑文章都会存一个修订版本(revision),新建却没用上的自动草稿(auto-draft),躺在回收站里的文章,成千上万条垃圾评论,还有插件反复写入的临时缓存和无用 meta 数据。这些东西不会自己消失,越攒越多,既占空间又拖慢查询。本文教你用一套安全、可复用的 SQL 给数据库做一次彻底瘦身,并附上防止再次堆积的长期配置,照着做就能让 WordPress 轻快起来。动手前请务必完整备份数据库。
故障原因分析
- 文章修订版本无上限堆积。WordPress 默认对每篇文章保存所有历史修订,一篇文章被反复编辑几十次,就会留下几十条重复记录,占用大量 wp_posts 和 wp_postmeta 空间。
- 自动草稿长期残留。你在后台点过”新建文章”却没发布,系统就写了一条
post_status='auto-draft'的记录,日积月累数量可观。
- 回收站和垃圾评论堆积。删掉的文章默认进回收站不彻底清除;没开反垃圾的站点会积累大量
comment_approved='spam'的垃圾评论。
- 孤儿 postmeta / commentmeta。文章或评论被删除后,它们对应的 meta 记录没有被级联清理,变成指向不存在对象的孤儿数据。
- wp_options 被 autoload 缓存撑大。很多插件把缓存、日志、临时数据塞进 wp_options 并设为自动加载,每次请求都要加载它们,既占空间又拖慢速度。
分步解决方案
第零步:备份
在 phpMyAdmin 里选中数据库,导出完整 .sql 并保存到本地。清理类操作用 DELETE,执行后无法撤销,备份是唯一保险。下面的 SQL 中表前缀 wp_ 请替换成你自己实际的前缀。
第 1 步:清理文章修订版本
先看有多少:
SELECT COUNT(*) FROM wp_posts WHERE post_type = 'revision';
确认后删除:
DELETE FROM wp_posts WHERE post_type = 'revision';
再顺手清理与修订版本关联的 meta:
DELETE FROM wp_postmeta
WHERE post_id NOT IN (SELECT ID FROM wp_posts);
第二条语句会删除所有”父文章已不存在”的孤儿 meta,范围比只删修订版本的 meta 更大、更彻底。
第 2 步:清理自动草稿
DELETE FROM wp_posts WHERE post_status = 'auto-draft';
如果你确定要一次清掉回收站里的无用文章(谨慎,会永久删除):
DELETE FROM wp_posts WHERE post_status = 'trash';
第 3 步:清理垃圾评论
先统计:
SELECT COUNT(*) FROM wp_comments WHERE comment_approved = 'spam';
再删除垃圾评论和它们的 meta:
DELETE FROM wp_comments WHERE comment_approved = 'spam';
DELETE FROM wp_commentmeta
WHERE comment_id NOT IN (SELECT comment_ID FROM wp_comments);
如果你还想一起清理被标记为回收站的评论(comment_approved = 'trash'),可把筛选条件改成 IN ('spam','trash')。
第 4 步:清理过期临时数据
WordPress 的 transient 缓存存在 wp_options 里,键名形如 _transient_xxx 和超时记录 _transient_timeout_xxx。已过期的可以安全删除:
DELETE FROM wp_options
WHERE option_name LIKE '_transient_timeout_%'
AND option_value < UNIX_TIMESTAMP();
删除超时记录后,对应的 _transient_ 数据也应一并清理:
DELETE o FROM wp_options o
JOIN wp_options t
ON t.option_name = CONCAT('_transient_timeout_', SUBSTRING(o.option_name, 12))
WHERE o.option_name LIKE '_transient_%';
不确定的临时选项建议先 SELECT 看看,别误删正在生效的缓存。
第 5 步:检查 wp_options 的 autoload 大户
按大小列出自动加载选项,看看是谁在拖后腿:
SELECT option_name, LENGTH(option_value) AS 长度
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 30;
对于已卸载插件残留、明显过时的选项,可把它的 autoload 关掉减少每次请求负载,或删除。删除前确认不属于核心或在用插件。
第 6 步:优化数据表,真正回收空间
删除只是打标记,InnoDB 不会自动把空间还给磁盘,必须优化表:
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;
OPTIMIZE TABLE wp_comments;
OPTIMIZE TABLE wp_commentmeta;
优化期间表会短暂锁定,放到访问低峰执行。
第 7 步:从源头减少垃圾再生
在 wp-config.php 里限制修订版本数量(放在 / That's all, stop editing! / 之前):
define( 'WP_POST_REVISIONS', 5 );
还可以把回收站自动清空周期设为 7 天:
define( 'EMPTY_TRASH_DAYS', 7 );
再装一个反垃圾评论插件拦截 spam,并考虑用对象缓存插件替代把缓存写进 wp_options 的做法。
第 8 步:验证
清理后打开几篇文章确认内容完整,后台”评论”和”回收站”数量正常,前台访问流畅;用本文第 5 步的查询再对比一下优化前后的表大小,通常能看到明显下降。
常见踩坑点
- 不备份直接 DELETE。清理语句不可逆,先导出。
- 误删 autoload 里的在用选项。禁用插件相关的可能没事,核心/在用插件的选项删了会出故障,先查再用。
- 只删数据不 OPTIMIZE。不优化,磁盘空间不会真正释放。
- 表前缀写错。以实际数据库里的表名为准。
- 把
_transient_缓存全删导致性能抖动。缓存被清后要重新生成,最好在低峰期做。 - 从不设防。不限制修订版本、不装反垃圾插件,垃圾很快又会堆回来。
总结
给 WordPress数据库清理垃圾,核心就是四类目标:修订版本、自动草稿、垃圾评论和无用的 meta / transient 数据。用本文给出的 SQL 逐项清理,再执行 OPTIMIZE 回收空间,就能让数据库体积和后台响应速度都有明显改善。更关键的是”防大于治”:在 wp-config.php 里限制修订版本、设置回收站自动清空、装反垃圾插件,才能让数据库长期保持清爽。整套操作都不难,唯一不能省的就是清理前的那次完整备份。
