wp_options 表是 WordPress 中最重要的表,一切程序设置、主题设置和绝大多数插件的设置均保存在此。在使用 WordPress 的过程中,测试插件与插件的反安装功能不完善,都很容易造成 wp_options 表的产生大量垃圾数据,这不仅占据了大量的数据库空间,还使数据库查询的效率降低。wp_options 表中的垃圾数据主要有两种:


无效的插件设置:一般来说,安装 WordPress 后,必定会大量安装使用各种插件体验,直到一段时间之后才会开始稳定的固定使用几款插件。无用的插件虽然被删除掉了,但是其保存在的数据库中的设置却没有被删除(80% 以上的插件没有提供删除自身添加的数据库数据的功能,所以我也希望插件的作者都能够提供彻底反安装的功能), 从而出现了大量垃圾数据。对于大部分插件来说,其在数据库中的数据命名都是源自于插件名称或者缩写,比如自动文章关联插件“Yet Another Related Posts Plugin”,它在数据库中的数据全部以“yarpp_”起始。这样我们就可以在 PHPMyAdmin 中确定相关的条目,删除即可。如果了解 MySQL 的语法,也可以执行:

DELETE FROM wp_options WHERE option_name LIKE 'yarpp_%'

如果我们早就忘记了安装过什么插件插件的名字是什么呢?单凭经验也很难确定哪些是垃圾数据哪些是有用的数据,不过有一点很重要:全新安装的 WordPress 3.1.3 版 wp_options 数据库条数为118条(option_id 1~118),也就是说位于这之后的所有条目都是由用户后来的调整和主题、插件产生的,后面的条目可以尝试删除,当然过程中要胆大心细,提前备份好数据库以防出现问题。另一个比较稳妥的方案就是在本地全新建立一个 WordPress,配置好之后将数据库导入到主 WordPress 数据库中。

无用的 RSS Feed Cache:其实这才是 wp_options 表变得庞大的最重要原因,如果你在 wp_options 表中发现了大量 option_name 以“_transient”开头的数据,那就是它没跑了。先说说这玩意儿是干嘛用的,这玩意就是 WordPress 程序中引入 RSS Feed 后产生的缓存,在表中的表现主要有这四种:

  • _transient_feed_* Feed 内容
  • _transient_feed_mod_* Feed 最后更改时间
  • _transient_timeout_feed_* Feed 缓存保存期限
  • _site_transient_* 这种是 WordPress 自身记录的一些信息,也是没用的

这玩意是如何产生的呢?如果你在你的博客中使用了 RSS 小工具;如果你在后台开启了“博客引入链接”、“WordPress China 博客”、“其它 WordPress 新闻”;如果你的插件中引入了 RSS 小工具显示新闻比如 NextGen Gallery。只要你看到了这些东西,那就会在数据库中产生这些垃圾数据(或许说是无用数据更为恰当),简直防不胜防。以我的博客为例,2个月的时间 wp_options 表就被这种数据撑大了600KB,网络上甚至有人达到了十数 MB 之巨。经过验证,这种数据清除后也会不断的产生,除非你能保证不去后台有 RSS Feed 小工具的页面,所以我制作了以下这个小程序。

<?php
header('Expires: Thu, 01 Jan 1970 00:00:01 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Expires:-1');
header('Cache-Control:no-cache');
header('Pragma:no-cache');
 
$hostname_blog = 'localhost';//数据库地址,一般是 localhost
$database_blog = 'wordpress';//数据库名
$username_blog = 'username';//数据库用户名
$password_blog = 'password';//数据库用户密码
$prefix_blog = 'wp_';//Wordpress 表的前缀,默认是 wp_
 
$blog = mysql_pconnect($hostname_blog, $username_blog, $password_blog) or trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db($database_blog, $blog);
 
//---------------------清除垃圾信息-------------------------
mysql_query('DELETE FROM ' . $prefix_blog . 'options WHERE option_name REGEXP "_transient_"');
 
//---------------------重新排列序号-------------------------
mysql_query('ALTER TABLE ' . $prefix_blog . 'options DROP option_id');
mysql_query('ALTER TABLE ' . $prefix_blog . 'options ADD option_id BIGINT( 20 ) NOT NULL AUTO_INCREMENT FIRST , ADD PRIMARY KEY ( option_id ) ');
 
//--------------------优化 wp_options 表----------------------
mysql_query('OPTIMIZE TABLE' . $prefix_blog . 'options');
 
//------------------------结束------------------------------
 
echo 'ok';
 
?>
  • 基本功能:先删除所有以“_transient”开头的数据,再把 wp_options 表的 option_id 按顺序重新排列(我喜欢序号排列不间断),最后优化该表。
  • 使用方法:
    1. 代码复制到文本编辑器,将数据库名,数据库地址,数据库用户名,数据库密码和数据库前缀填好以后,另存为一个扩展名为.php的文件;
    2. 上传到主机,访问文件地址执行;
    3. 最好按Ctrl+F5多执行一遍以确保浏览器显示的信息不是缓存;
    4. 一切 OK,定期执行即可。
  • 注意事项:
    1. 不会对其它表进行操作,但运行前请先备份数据库,以防万一。
    2. 可根据注释删除不需要的功能。
    3. 请注意文件的安全,或用完及时删除,或设定一个 000 权限,避免泄露数据库信息(仅从 HTTP 正常访问无法看到内容,但如有人控制了 FTP 便可从中得知数据库信息)。

你也可以在 MySQL 中执行:DELETE FROM wp_options WHERE option_name REGEXP "_transient_"来删除上述无用数据。

最后强烈推荐 WP-DBManager 这个插件,可以定期/手动备份数据库,并将数据库 Gzip 后发送到指定邮箱,可以定期/手动修复和优化数据库,可以 Drop 表,可以在后台执行 SQL 语句。非常强大、非常方便。

  1. […] 本文參考:http://xia.im/clean-wordpress-database-wp-options-table/ 和 http://kn007.net/topics/optimization-clean-up-wordpress-database-wp_options-table/,感謝二位。來訪數: (0) Posted by: 海捷 (hijay) // WORDPRESS // 三月 26, 2014 […]

  2. 呃 苦逼了,今天我看了下百度统计的内容,一天下来就 1 个 IP,然后以为网站出了什么问题,一整天神经兮兮的,接着刚刚到百度统计又看了下,检查了代码是否正确安装,果然,检测不到代码,因为主题中设定了一个函数 - 在后台设置 head 标签前添加代码,清理 option 表的时候顺带的把其中的设置项也搞没了。看来又得修改主题了。。。

    • @诸葛小觉
      我这段代码应该不会删除主题的设置吧?统计代码我一般都直接写死在主题文件里面。

    • @小虾
      对呀,所以这次之后我就将代码写进模板里面了,至于为什么会涉及到就得查看下数据库表对比下了

    • @诸葛小觉
      你对比一下吧,找找那个数据的名字,我好修改一下代码。谢谢!

    • @小虾

      option_name:catchbox_options_webmaster
      option_value:a:2:{s:14:"tracker_header";s:273:"
      var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "//hm.baidu.com/hm.js?b9adef6a24db592ce39805d660cd588b";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })();
      ";s:14:"tracker_footer";s:0:"";}
      

      其中 catchbox 是主题名

    • @小虾
      刚刚再次进行搜索了一下,数据库里面是还有这项数据的,就是 ID 发生了变化,所以主题上不能接入了。
      这里想问的是一下重新排列序号的代码是必须弄上去的吗?因为 ID 的变化对主题的应用可能有些影响。再问个问题就是序号不重新排列又会出现什么问题呢?

      //--------------------- 重新排列序号 -------------------------
      mysql_query('ALTER TABLE ' . $prefix_blog . 'options DROP option_id');
      mysql_query('ALTER TABLE ' . $prefix_blog . 'options ADD option_id BIGINT( 20 ) NOT NULL AUTO_INCREMENT FIRST , ADD PRIMARY KEY ( option_id ) ');
      
    • @诸葛小觉
      一般来说序号不影响内容,因为程序都是根据 option_name 定位的,而且我肯定我这段代码不会删除你主题的设置。
      不用重新排序序号没有任何影响,所以你删去这段就没事了。

    • @小虾
      行,可能这主题是通过 ID 来进行定位的,我直接删了吧

  3. 直接放上去,然后每一个阶段我自己添加了说明,但是最后虽然说执行成功了,但是数据库中的 option 表并没有减少,然后我直接在 phpmyadmin 中通过 sql 写入你上边的 4 条命令,成功优化了 option 表,虽然过程还是通过命令完成的,但是还是谢谢了 :lol:
    不过如果能够提供更完美的代码就更好了,同时我是放在服务器文件根目录上的,是不是有这个因素在影响呢?还是放在 plugs 插件目录中再执行呢?

    • @诸葛小觉
      放在哪里都可以,出问题看看你的前面的设置有没有填对,比如数据库地址是不是 Localhost,提示 OK 是因为没有增加别的提示判断。

    • @小虾
      哦~ 现在知道问题所在了,是因为我没有填写 $prefix_blog 这个数据库前缀,刚刚再次操作了一下可以了,不过在执行之后等了一会才能打开数据库,可能是需要一点时间执行吧,太急了,差点吓到俺,而且刚刚没进行备份,呼~ 幸好最后成功了~

    • @诸葛小觉
      不会吧,这个过程很快的,一般只要 0.001 秒就能完成,慢可能是有其它原因 :appall: 。这段代码可以说是 99% 安全,不过还是建议操作前一定要备份(注意事项中也写到了),数据库里面的东西可是无价的 :smile:

    • @小虾
      估计这服务器的问题,现在用的这个服务器什么都好,功能和服务都 ok,就是在使用谷歌内核的浏览器进入 phpmyadmin 的时候会很慢,不明真相....

  4. 帮助很大,在这儿谢谢了!一直想找,但是不知道怎么找,这次通过一系列搜索来到贵站真是太棒了!!

  5. [...] 如果你懒得搞,就用 WP clean up 加上小虾的方法 [...]

  6. 很好用,减少了很多无用数据

  7. 我的 2MB 了,看来的清理下了