wordpress支撑百万文章解决方案

作为一个博客系统,wordpress在易用性和可扩展性上都非常出色。后题用户体验是非友好,插件众多。然而由于定位的问题,wordpress无法支撑大量文章。当文章数量达到上万的时候,有些主题的前台可能会非常卡。当文章数量达到数十万的时候,wordpress后台可能会特别卡。更何况大部分插件并没有在性能上下功夫,插件越多,wordpress越卡。那么有没有什么方案能让wordpress支撑大量文章?十万,百万,甚至更多?

支撑百万数据并不是存入一百万文章就可以了。实际上百万文章对mysql来说毫无压力。在mysql中,百万文章仅仅是百万条记录而已。导致缓慢的是mysql的查询。对于百万条记录的数据库,一次全表扫描的代价是十分昂贵的!很不幸,wordpress的经常会干一些扫描全表的事情!

整体优化

需要去掉所有查询中带有的SQL_CALC_FOUND_ROWS,这会扫描表,速度十分慢!对于大量的数据,查询的数目应该是缓存过后,或者是事先计算好的!

需要去掉所有的COUNT操作,这也会导致扫描条件中的所有行,如果条件没有索引,将会导致扫描全表!

由于wordpress查询复杂,针对每一种查询设置一个计数器不太现实,可以考虑使用查询结果缓存的方式来减少扫描全表的次数。缺点就是计数会有延迟。

首页优化

一般来说,达到百万文章级别的站点,首页应该是一个展示很多分类文章的页面。但是由于wp在初始化的时候就会根据url中的查询去数据库查询一些文章,首页是根据时间倒序查询,因此当不需要最新文章的时候,可以利用钩子去掉这部分查询。

文章页优化

看看文章页面,似乎没有什么费时间的查询,基本上就是id查询内容,用到了索引,但是其中有一个翻页的问题,其中有一个翻页的功能是可以筛选出相同分类的上下篇文章,这种查询的sql语句如下

mysql> SELECT p.ID FROM wp_posts AS p
  
INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE p.post_date > '2017-07-04 09:57:50' AND p.post_type = 'post' AND tt.taxonomy = 'category' AND tt.term_id IN (4) AND p.post_status = 'publish' ORDER BY p.post_date ASC LIMIT 1;

使用explain看看

mysql> explain SELECT p.ID FROM wp_posts AS p INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE p.post_date > '2017-07-04 09:57:50' AND p.post_type = 'post' AND tt.taxonomy = 'category' AND tt.term_id IN (4) AND p.post_status = 'publish' ORDER BY p.post_date ASC LIMIT 1\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: tt
 type: const
 possible_keys: PRIMARY,term_id_taxonomy,taxonomy
 key: term_id_taxonomy
 key_len: 106
 ref: const,const
 rows: 1
 Extra: Using temporary; Using filesort
 *************************** 2. row ***************************
 id: 1
 select_type: SIMPLE
 table: tr
 type: ref
 possible_keys: PRIMARY,term_taxonomy_id
 key: term_taxonomy_id
 key_len: 8
 ref: const
 rows: 5576
 Extra:
 *************************** 3. row ***************************
 id: 1
 select_type: SIMPLE
 table: p
 type: eq_ref
 possible_keys: PRIMARY,type_status_date
 key: PRIMARY
 key_len: 8
 ref: aikanwen.tr.object_id
 rows: 1
 Extra: Using where
 3 rows in set (0.19 sec)

看起来就是个灾难现场,这种查询会随着分类的增加而变得奇慢无比,因为有时候分类和标签可能会达到几万几十万个!

分类优化

同首页,只查询分类的最新一些文章,甚至是提前生成的静态页面。

插件优化

wordpress最常用的插件可能是wp_postviews了,但是对于百万文章的wordpress来说,这个插件可能是个灾难(如果你用到了它的排行榜的话)。

这个排行榜会使用一个如下的查询

SELECT wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( 
 wp_postmeta.meta_key = 'views'
) AND wp_posts.post_type IN ('post', 'page', 'attachment') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10;

这种查询也是一个灾难,对于wp来说,wp_post_meta表中根本没有meta_key 和 meta_value的索引,也是根本无法使用索引做排序,所以只能使用filesort,需要全表扫描。可以看看explain。

mysql> explain SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( wp_postmeta.meta_key = 'views' ) AND wp_posts.post_type IN ('post', 'page', 'attachment') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10 \G;
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: wp_postmeta
 type: ALL
 possible_keys: post_id,meta_key
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 67053
 Extra: Using where; Using temporary; Using filesort
 *************************** 2. row ***************************
 id: 1
 select_type: SIMPLE
 table: wp_posts
 type: eq_ref
 possible_keys: PRIMARY,type_status_date,post_author
 key: PRIMARY
 key_len: 8
 ref: aikanwen.wp_postmeta.post_id
 rows: 1
 Extra: Using where
 2 rows in set (0.17 sec)

这种排序一次,基本就是个灾难。别说百万,十万文章蜘蛛都能搞挂了。

事实上,在文章达到百万的时候,涉及到数据库读写的插件最好都不要乱用,一不小心就是个灾难。

后台优化

后台页面在打开的时候会查询当前作者的所有文章以及各个状态的文章数量,这会扫描全表,别说百万文章了,就算二十万文章也会卡死。

最好的办法就是去掉这些查询,然而去掉这些查询会让后台展示不正常,因此只能利用缓存将这些数量存起来,这样后台的速度就很快了。虽然会有展示不及时的问题,但是到了这个文章量,这已经不是主要的问题了。

全站缓存

这是最重要的一步了,再多的优化也只能保证你的百万文章站点能正常打开,但是如果访问的人一多,站点依然会卡死,甚至服务器宕机。这个时候就必须上全站缓存。看了一下市面上所有的缓存插件,也只有一个满足要求了——imwpcache。

imwpcache支持永不过期的缓存,并且支持使用sqlite作为缓存,这比使用文件缓存更好。文件缓存太分散,几万文章还好,当达到了百万时候,清理这些缓存简直是一个灾难。

总结

经过这些优化之后,支撑百万文章基本不是问题。对于普通用户来说,做到这些可能会比较困难,尤其是主题。现在市面上主题基本不会考虑这么多的文章量,文章量一上来,网站基本就瘫痪了,所以目前最佳策略还是用缓存插件,当然如果你有动手能力,也可以尝试一下去掉这些耗资源的查询,虽然可能会损失一些功能,但是能支撑这么多文章足以弥补这些损失。

你可能还喜欢下面这些文章

wordpress慢了,来用memcache和cdn加速一下吧

我用的vps,用了wordpress之后速度慢了不少,内存,cpu,涨的都厉害,很直观。于是,写插件吧,虽然wordpress的插件很多,缓存插件也不少,但满足我的需求的却是没有。我要的是这样的1.使用memcache缓存整个页面。(memcache可压缩缓存,并且我的页面并不多,因此占用并不大)2.在入口处就加载并且使用缓存(仅仅加载一个我预定义的缓存读取php文件,io极少,速度极快)需求很少,因为是特定的需求,十分简单,我要的就是整个页面都跑在内存中!写插件吧......几天之后,一个插件完成了。hccache缓存插件加速后台菜单是酱紫的hccache菜单点开之后是酱紫的能够定义缓存过期

查看varnish统计信息命令:varnishstat

varnishstat是一个查看当前varnish实例的实时运行状态信息。命令以及参数如下:varnishstat 以下选项可用: -1不再显示不断更新的显示,而是将统计信息打印到stdout。-f <glob>Field inclusion glob. Use backslash to escape characters. If the argument starts with '^' it is used as an exclusion glob. Multiple -f arguments may be given, and they will be ap

使用sublime+platuml高效画图

程序员难免要经常画流程图,状态图,时序图等。以前经常用 visio 画,经常为矩形画多大,摆放在哪等问题费脑筋。有时候修改文字后,为了较好的显示效果不得不再去修改图形。今天介绍的工具是如何使用 Sublime + PlantUML 的插件画流程图,状态图,时序图等。这是一种程序员看了就会爱上的画图方式:自然,高效。什么是 PlantUMLPlantUML 是一个画图脚本语言,用它可以快速地画出:时序图流程图用例图状态图组件图简单地讲,我们使用 visio 画图时需要一个一个图去画,但使用 PlantUML 只需要用文字表达出图的内容,然后就可以直接生成图片。看一个最简单的例子:软件安装这些软件

sublime优秀插件推荐

最佳的Sublime Text 插件朋友们你们好!我尝试着收集了最佳的ST插件,这些插件真的会改善你的工作流程。我搜索了很多网站,下面是我的成果。WebInspector在 JavaScript调试方面,这是一个令人惊讶的工具,Sublime上的完整的代码检查工具。功能:使用绝对路径储存在用户设置中的项目断点,控制台,分步和断点调试器,栈追踪。这些都能够很棒的工作!而且Mozilla还提供了一个插件Fireplay让你连接到Firefox 开发工具和最简单的调试器JSHintEmmet编辑器中最流行的插件之一。Emmet,前身Zen Coding也是web开发者提高生产力最有效的方法之一。按下

强化twenty fifteen主题,twenty fifteen pro主题制作过程

被最新的twenty fifteen主题迷上了,这就是我心目中的样式!但有功能还是需要添加的,因此在twenty fifteen的主题基础上,增加了一些功能,命名为twenty fifteen pro主题,目前我所用的主题就是twenty fifteen pro主题。目前增加的功能有这些1.专辑文章将一些文章整个成专辑,比如之前胡超的sublime这个专辑,随便点进去一篇文章,左侧栏都会出现该专辑的系列文章,并且在后台还可以手动控制其排序。这样的好处就是能够将同类别,教程之类的文章聚合起来,更加利于阅读。2.页脚文字增加统计或者版权文字,备案号等等一些附加的信息可能是需要的,但很遗憾twent

gcc/g++编译参数详解

编译步骤gcc 与 g++ 分别是 gnu 的 c & c++ 编译器。gcc/g++ 在执行编译工作的时候,总共需要4步:预处理,生成 .i 的文件将预处理后的文件转换成汇编语言, 生成文件 .s 有汇编变为目标代码(机器代码)生成 .o 的文件连接目标代码, 生成可执行程序 参数详解-x language filename参数含义为指定文件所使用的语言。根据约定,C语言的后缀名称为".c",而 C++ 的后缀名为".cpp"或".cc",但如果你的源代码后缀不约定的那几种,那么需要使用-x参数来指定文件所使用的语言。这个参数对他后面的文件名都起作用。 可以使用的参数吗有下面的这些:

varnish的基本工作原理

Varnish是一个HTPP反向代理缓存,它接受来自客户端的请求并试图从缓存中取出相应的数据来应答,如果缓存中并没有相应的数据,它将会把请求指向后端机器,获取并且储存响应的数据,之后再交付给用户。当varnish有缓存的时候响应通常只需要几微秒的时间,比直接访问后端机器通常要快两个数量级,所以要做的就是尽可能的将页面缓存到varnish中。varnish可以根据后端响应的内容来决定是否储存,在响应头中加入cache-control将会被varnish缓存。使用cookie可以让varnish不缓存。这些都是可以在一个vcl的配置文件( Varnish Configuration Languag

MySQL开启慢查询日志以及慢查询日志分析

mysql满查询有助于让我们发现系统中瓶颈所在。开启方法默认情况满查询应该关闭,如果需要分析则需要手动开启。mysql> show variables like '%slow_query_log%'; +---------------------+--------------------------------------+ | Variable_name | Value | +---------------------+--------------------------------------+ | slow_

记录一下使用中PDO出现的一个问题:Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll().

在使用PDO的时候,一条sql语句打死都不执行,dump一下errorInfo试试,出现这样的错误信息问题描述居然告诉我还有语句没有执行完成?当前的查询未能执行,逗我么!考虑使用fetchAll,或者开启缓冲查询,行,你说得对....问题出现的使用场景服务器服务器为linux,安装了一个什么面板套件之类的,不是自家机器,也懒得去折腾,在本地的windows环境并没有该问题。程序笔者在对数据库的一个计数字段进行更新的时候,首先会先查询这个记录是否存在,如果存在则进行更新,如果不存在则先插入。问题就出现在记录不存在的时候,当我查询这条不存在的记录时候,发现这个记录不存在,然后进行插入,发现之前的查

sublime安装package control,让插件安装更简单

package control是什么东东?sublime要如何安装package control呢?且往下看。package control就是sublime的插件管理中心,你可以通过这个东西来安装,更新或者卸载插件。插件能够增强sublime的功能,这个就不废话了安装package control1.使用快捷键 Ctrl+` (这个就是键盘Esc下面的那个), 打开sublime的控制台(这个控制台可以输入并且执行python代码)sublime text3sublime text2手动安装可能由于各种原因,无法使用代码安装,那可以通过以下步骤手动安装Package Control: 点击

赞赏

微信赞赏支付宝赞赏

《wordpress支撑百万文章解决方案》有2条评论

  1. 我也在使用这款插件,不错,而且不会占用cpu资源,我是选择sqlite缓存方式,目前的唯一问题是设置过期时间,但是到时间后不会删除缓存文件,希望站长开发者后期能解决。

回复 Daniel 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注