网站运维

WordPress 数据库越用越臃肿:垃圾数据清理实操

一个 WordPress 站用了两三年,数据库从最初的 20MB 涨到几百 MB,页面打开越来越慢。

涨出来的这部分,绝大部分不是你的文章和订单,是垃圾:文章修订版本、自动草稿、过期的临时缓存、已经删掉的插件留下的配置数据。

清理这件事不难,但有风险——操作不当可能删掉真实数据。这篇讲清楚哪些能删、哪些不能碰、怎么安全地删。

一、先看你的数据库里装的都是什么

进 phpMyAdmin,或者用命令行:

SELECT table_name,
       ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb,
       table_rows
FROM information_schema.tables
WHERE table_schema = '你的数据库名'
ORDER BY (data_length + index_length) DESC
LIMIT 15;

注意看:如果 wp_options 或者 wp_postmeta 特别大(几百 MB),那基本就是有问题了。正常的内容站,最大的表应该是 wp_posts。

二、四类最常见的垃圾数据

1. 文章修订版本(revisions)

WordPress 每保存一次文章就存一个修订版。一篇改了 20 次的文章,数据库里就有 21 条记录。一千篇文章的站,修订版轻松上万条。

看看你有多少:

SELECT COUNT(*) FROM wp_posts WHERE post_type = 'revision';

上万条就值得清理了。

能不能删:能。但你可能会想保留最近的几个版本以防万一。建议保留最近 3 个,或者全部删掉——说实话,大多数人从来没用过修订版恢复功能。

2. 自动草稿和回收站

SELECT COUNT(*) FROM wp_posts WHERE post_status = 'auto-draft';
SELECT COUNT(*) FROM wp_posts WHERE post_status = 'trash';

自动草稿是你点「写文章」但没保存时自动生成的,堆积很快。回收站里的是你删了但没清空的。

能删。回收站清空前确认里面没有误删的内容。

3. 孤立的 postmeta(无主数据)

这个比较隐蔽:文章被删了,但它对应的 meta 数据没跟着删,留在表里变成孤儿。

SELECT COUNT(*) FROM wp_postmeta
WHERE post_id NOT IN (SELECT ID FROM wp_posts);

几万条很常见。能删,这些数据已经没有任何东西引用它们了。

4. 过期的 transient(临时缓存)

Transient 是 WordPress 的临时缓存机制,很多插件用它缓存 API 结果。问题是大量 transient 过期了也不会自动消失。

SELECT COUNT(*) FROM wp_options
WHERE option_name LIKE '_transient_timeout%'
  AND option_value < UNIX_TIMESTAMP();

这是「已经过期但还占着空间」的数量。WooCommerce 站尤其严重——它会为每个访客的购物车、每次价格计算生成 transient。

三、最该重点检查的:wp_options 的 autoload 数据

这一项对性能的影响最大,但很多人不知道。

WordPress 每次页面加载,都会把所有 autoload = 'yes' 的 options 一次性读进内存。不管你用不用得到。所以这个数据越大,每个页面都越慢。

看它有多大

SELECT ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS size_kb
FROM wp_options WHERE autoload = 'yes';
大小 判断
< 500 KB 健康
500 KB – 1 MB 可以关注
1 – 3 MB 明显拖慢,建议清理
> 3 MB 严重问题,必须处理

找出占地方的大户

SELECT option_name,
       ROUND(LENGTH(option_value) / 1024, 2) AS size_kb
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 20;

排在最前面的,通常是这几类:

  • 已卸载插件的残留——插件删了,数据留下了。看 option_name 前缀能不能对上你还在用的插件,对不上就是残留
  • 缓存类的大块数据——某些插件把整个缓存塞进 options
  • 主题的巨型配置——一些页面构建器会把大量页面数据存在 options 里

怎么安全地删

看到名字对不上的,先查一下这个 option 是什么:

SELECT * FROM wp_options WHERE option_name = '可疑的名字';

看一眼 option_value 的内容,判断是不是垃圾。确认之后再删:

DELETE FROM wp_options WHERE option_name = '确认无用的名字';

不确定的别删。留着最多占点空间,删错了网站可能直接崩。

四、三种清理方式,选一个

方式一:插件清理(推荐新手)

装 WP-Optimize 或 Advanced Database Cleaner。

优点:点几下就行,会自动跳过不确定的数据。缺点:清理力度相对保守。

操作前务必先备份数据库。

方式二:SQL 手动清理(可控性最强)

-- 1. 删所有修订版
DELETE FROM wp_posts WHERE post_type = 'revision';

-- 2. 删自动草稿
DELETE FROM wp_posts WHERE post_status = 'auto-draft';

-- 3. 清空回收站
DELETE FROM wp_posts WHERE post_status = 'trash';

-- 4. 删孤立的 postmeta
DELETE FROM wp_postmeta WHERE post_id NOT IN (SELECT ID FROM wp_posts);

-- 5. 删过期的 transient
DELETE FROM wp_options WHERE option_name LIKE '_transient_timeout%' AND option_value < UNIX_TIMESTAMP();
DELETE FROM wp_options WHERE option_name LIKE '_transient_%' AND option_name NOT LIKE '_transient_timeout%'
  AND option_name NOT IN (SELECT REPLACE(option_name, '_transient_timeout_', '_transient_') FROM (SELECT option_name FROM wp_options WHERE option_name LIKE '_transient_timeout%') AS t);

-- 6. 清理垃圾评论
DELETE FROM wp_comments WHERE comment_approved = 'spam';
DELETE FROM wp_comments WHERE comment_approved = 'trash';

每条执行完可以用 SELECT ROW_COUNT(); 看影响行数。

方式三:WP-CLI(有 SSH 的话最舒服)

wp post delete $(wp post list --post_type='revision' --format=ids) --force
wp transient delete --expired
wp comment delete $(wp comment list --status=spam --format=ids) --force

五、清理之后别忘了这一步

DELETE 语句执行完,磁盘空间不会立刻释放——InnoDB 会把删除的空间标记为可复用,但文件不会变小。

要真正回收空间:

OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;

注意:OPTIMIZE TABLE 会锁表,大表可能要跑几分钟,期间网站会卡。挑在流量最低的时候做。

或者更彻底的方式(推荐):导出整个数据库再导入一次,相当于重建:

mysqldump -u用户 -p 数据库名 > dump.sql
mysql -u用户 -p -e "DROP DATABASE 数据库名; CREATE DATABASE 数据库名;"
mysql -u用户 -p 数据库名 < dump.sql

这个操作风险高,一定要先确认备份可用。

六、让它不再堆积:三个设置

1. 限制修订版数量

在 wp-config.php 加:

define( 'WP_POST_REVISIONS', 3 );   // 只保留最近 3 个
// 或者彻底关闭:define( 'WP_POST_REVISIONS', false );

2. 延长自动保存间隔

define( 'AUTOSAVE_INTERVAL', 300 );  // 5 分钟,默认 60 秒

3. 装个清理插件设定定期任务

WP-Optimize 可以设置每周自动清理一次,设好就不用管了。

七、效果预期

清理能带来多少提升,取决于你的数据库有多脏:

  • 数据库小、autoload 正常:可能感觉不到变化。这时候别指望清理能提速,瓶颈在别处
  • autoload > 2MB:清理后每个页面通常能快 100-500ms,效果非常明显
  • 几万条修订版:后台文章列表加载速度会有肉眼可见的变化

最后

数据库清理是低风险、中等回报的维护动作。它不会让你的站脱胎换骨,但能让一个用了几年的老站回到正常水位。

建议节奏:每半年做一次,配合定期备份。做之前备份,做完看一眼网站正常不正常,就这些。