Andy's Blog » » WordPress效率问题剖析及重写WordPress

WordPress效率问题剖析及重写WordPress

昨天一个IXWEBHOSTING空间受到警告,被停了数据库,原因是占用资源太厉害,WORDPRESS实在是个吃资源的大户,特别是CPU资源。

一直以来,一直都想重新写个简洁高效版的WORDPRESS,这2天动手写了一下,发现了一些WORDPRESS速度慢的一些主要原因。以及我的解决方法。

1. 一篇文章多个分类:
每篇文章可以同时属于多个分类,在 wp_post2cat 中来实现一篇文章属于多个分类,这样就会造成列表查询时,为了得到每一篇文章的所属分类,会有非常多次数的查询

下面我说说WP中每一篇文章的分类链接是如何出来的:
1.1 显示列表时,会先从wp_posts中取出ID,标题,内容等主要字段
1.2. 再根据上一步得到的文章ID 在wp_post2cat中选择分类ID
1.3. 再根据得到分类ID后,再到`wp_categories`这个表中取每个分类ID的名称等内容

每一个条列表里的文章都要重复进行这些操作,数据库查询次数太多了!不断的频繁向`wp_post2cat`和`wp_categories`表查询,这是瓶颈所在。

如果一篇文章只属于一个分类,就会非常快,因为只需要一次查询就搞定了,ID,标题,分类,内容,都可以一次性取得.而WP设计的结构就是这样,没有办法避免.所以只能从其他方面考虑优化。

解决方案:
在不改变WORDPRESS数据库结构的情况下,可以将整个`wp_categories`输出文本数组进行缓存,这样要取得分类名称,就可以直接从数组中取,速度快好几倍。
备注:本来我想将分类字段改成内容像 1,2,3 这样的字段,这样就可以实现一篇文章多个分类,但是反过来,要查询某一分类的文章,就不行了,还需要另外的表,所以wordpress的数据库表结构并没有什么问题,关键还是在于程序!另外在研究WORDPRESS数据库表的时候,发现有好多字段都设置得很大,像可以用TEXT的它却用LONGTEXT,可以用INT(10)的它却用INT(20)等等

分类的缓存,可以在后面我说到的根据首页缓存来定时更新,除非你闲着没事整天改文章的分类。

2. 边栏按月归档 ARCHIVE的分月列表
这是取月份列表的SQL语句

SELECT DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM `wp_posts` WHERE post_type = 'post' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC

这部份执行时间是比较多的,为了取得月份列表,对整个wp_posts表进行查询,实在不应该!而且每个页面,都会有这个操作!
这部份最最应该缓存!!!因为这玩意一个月更新一次缓存都可以了,不缓存的话,当文章有几万的时候,每个页面进行这个操作,是相当可怕的!
这部份缓存后只是一个数组,执行时间几乎是0
说到这里,还有个日历的区域,这个比按月归档要猛得多了,我觉得可以删除了,没有什么实际意义。

3. 边栏的分类列表
这部份看似简单,也要进行很多次数据库查询!虽然执行时间不算多,但查询次数实在太多了,因为有上下级的关系,这部份不必细说,和其他 CMS的分类表基本差不多,进行分类缓存后,这部份的速度,提升10倍,同时,也应用于上面的第一点。

WORDPRESS的程序结构设计的过于强大和复杂,数据库查询他本身已经是优化了的,要相信世界上这么多程序高手在写这个程序
正是因为这个强大的原因,程序考虑到太多的变动原因和太多的情况判断,导致效率非常低下,结构非常复杂,把一些非常简单的事都复杂化了

4. TAG部份
如果使用到TAG,和分类表基本一样的,最好也进行缓存
说到底,要速度快,就要进行缓存,进行最少次数的数据库查询,程序简单,再加上缓存,效率自然就高

目前WORDPRESS有WP-CACHE这个PLUGIN可以来做缓存用,但缺点太多
1. WP-CACHE是对整页进行缓存
2. 整站所有页面缓存时间都相同,无法控制首页,列表页,TAG页,搜索结果页,文章页不同的缓存时间

我重写的WORDPRESS只写完列表页和文章页,有2个版本
一个是超级优化的,仍然用WORDPRESS的原版数据库,分类和ARCHIVE缓存,不进行分类表的查询
将这些查询很耗时间的东西都做成局部缓存,在这一层之上,再做整页缓存,可以控制首页,列表页,TAG页,搜索结果页,文章页不同的缓存时间
内容仍然和WORDPRESS基本一样,包括标题,时间,分类,内容等
在3万文章的情况下,每页执行时间没有超过0.01秒的,而默认的WORDPRESS最少也要0.7秒,相差70倍,放到空间上,一页执行个6秒都是正常的,更不用说高负载的情况了,不被停空间才怪!
用上了局部缓存+整页缓存,优化到最后,执行时间基本和静态页面一致,因为最终的就是读取整个缓存页面

另一个是不进行缓存的版本,执行时间最少也在0.3秒以上,才发现,不缓存,对多个表进行查询进行多次查询是难免的,提升不了太大的效率

期待WORDPRESS也能应用好缓存,为爱好者们省点CPU资源吧。MYSQL不是那么好查询的,别没事整天查

本文来源21andy.com 转载请以超链接方式注明出处21andy.com
本文地址 http://www.21andy.com/new/20070216/591.html

Incoming search terms:

Tags:

本文地址: http://blog.21andy.com/20070216/591.html

9 评论 to “PHP开源CMS之MODx”

  1. lovewait 于 2007-02-17 15:26:06 发表:

    Andy,向你了解一下,WP能够承受多少的数据啊?
    07年想用WP来建站。

  2. andy 于 2007-02-17 16:51:36 发表:

    承受的数据,MYSQL方面是没有什么问题
    主要是数据一多程序就会很慢,默认的WP程序,不改进的话,过1万文章就会很慢
    我自己改的版本,20万文章都很快

  3. hhot 于 2007-02-18 02:21:41 发表:

    能共享一下你修改的WP版本吗? 非常期待

  4. Andy 于 2007-02-18 14:39:24 发表:

    我写的不是改的,只写完了列表和文章页,分类和ARCHIVE部份
    还有评论,RSS,搜索等没有写呢,是个半成品
    而且我写的是定性的东西,WP自身变化很多,像URL就可以规划成很多种,而我写的只有一种URL,而且也不考虑插件问题,我只用到了几个表中最主要的几个字段,其他的都没用到,所以,相当于已经不是WP了。

  5. Yimin 于 2007-02-18 16:32:37 发表:

    关于分类,可以在posts表中,增加categories字段,把文章的分类信息数组序列化后存进去。

  6. Andy 于 2007-02-18 16:55:34 发表:

    我本来是这么想的,可是反过来查某个分类列表的文章就用不到这个字段了
    如果用LIKE语句查,我就晕倒
    如果只是增加这个字段,post2cat表一有变动,这个字段相应的内容也要变,我觉得同样的内容,用2种方式存2个地方,是完全没有必要的,也是不应该的

  7. fcicq 于 2007-02-19 18:33:45 发表:

    :)
    偶对wp的性能确实也不满意.
    许多东西都是可以用现成的.
    偶也重新做了一个wp的前台,对数据库没有做任何修改.

    (http://www.fcicq.net/wp/?p=424)

  8. elliott 于 2007-03-22 13:34:34 发表:

    请问楼主是怎么缓存内容的?
    用开源的包还是自己写的?

  9. Noble 于 2007-04-08 09:16:04 发表:

    可以使用wpcache插件,来缓解。