[原创]Wordpress效率与其他程序评测与分析

     见到网上很多人貌似都十分推崇Wordpress,甚至很多从其他程序转过去的,就好像用wp够档次似的,也不知是因为看很多专业人士用,自己也要用,或是就因为wp是国外的程序的原因?

程序结构方面的详细的对比以后再发,先从最直接也是程序最重要的一个指标程序执行效率上看:

先说一下服务器环境,至强3.2G,1G内存,PHP5.2.5,Mysql5.0.51a,Windows server2003 IIS6.0  Wordpress2.5.1

1、在安装完不使用任何插件的情况下,只发表一篇日志,为防止iis运行时间过长对结果产生影响,发表完后重新启动服务器IIS,运行wordpress程序,我的天,就一片日志,如此慢!





就一篇日志,没有插件初次打开首页程序执行时间3.979秒,23次数据查询!刷新一下后,22次查询,0.640秒。跟我现在的ASP+Access的程序都不再一个档次上。在WEB程序上,超过0.3秒就算很大了。真是搞不清楚就是一个博客,为何如需要此多的数据查询。程序执行时间是反应程序健康及优化程度,服务器配置、优化情况的最直接的参数和体现。


也许你说是我服务器配置环境不好的原因,那就再比较一下其他类的程序在同样我的服务器环境下的执行时间,前几天看到Discuz6.1出来了,就拿它来做测试吧,以下分别是第一次和第二次程序执行时间:







再来试一下Sablog的:









    必须承认的是,我的服务器上跑PHP程序的网站不多,负载也不大,所以就没有专门针对PHP程序进行专门的优化,主要是mysql数据库参数的一些优化,也没有使用Apache。如果在Linux下,针对PHP环境进行特别的优化,利用加速程序,缓存等,PHP程序包括大型论坛执行时间在0.00X的数量级是很容易的,当然是说有一定数据量的情况下,并非拿来个空数据库甚至就十条白条数据的数据库来说读取数据快。但wordpress即使是一篇日志,也从未到0.0x的数量级


    其次,看别人的Wordpress博客最反感的就是长网页,说的不好听点,网页长了就叫又臭又长,也没有个列表模式,总是把一大堆的日志显示在首页上,既增加了数据库和服务器负载,又十分不便于快速浏览。尤其是第一次看人的博客想看看大体都写了些什么,拖着小小的滚动条眼睛费力搜索,实在累人不浅,也许你可能说,不是有搜索么,对啊,可我不知道你都写了些什么,如何搜索?还有一个朋友一开始用的WordPress,访问量大了,服务器直接导致经常死机,不得不换了其他的博客程序。

    其次,就算作为博客追求功能强,定制度高,但也不能比一个大型的PHP论坛如Discuz,PHPwind等论坛麻烦吧?测试程序执行时间,WP的效率远远比这些论坛都差。为什么一个小小的博客搞得竟然比论坛还慢?实在费解。更不用说再安装众多的插件了。


   最后,感觉还是不相信WP的执行效率就这么垃圾?于是不厌其烦的到google、baidu搜索其他Wordpress博客,结论是真证实了确实执行效率够垃圾(光说程序执行效率上)以下是结果:






1.027秒



0.489秒



1.42秒 服务器环境:Linux  Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.8b mod_auth_passthrough/2.1 mod_bwlimited/1.4 PHP/5.2.5 



4.2秒  服务器环境:Linux  Apache/1.3.41 (Unix) PHP/5.2.5 mod_ssl/2.8.31 OpenSSL/0.9.8c 



1.421秒  服务器环境:Linux  Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.8b mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.5



0.238秒  服务器环境:Linux  Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.8b mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.5



1.756秒  服务器环境:Linux  Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2



1.027秒



0.555秒  服务器环境:Linux  Apache/2.2.8 (Unix) mod_ssl/2.2.8 OpenSSL/0.9.8g DAV/2 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635



0.856 竟然有49次数据查询!!!



0.551秒  服务器环境:Linux  Apache/2.2.8 (Unix) mod_ssl/2.2.8 OpenSSL/0.9.8g DAV/2 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 




这个记录高!!11.407秒   服务器环境:Linux  Apache/2.2.6 (Fedora) 



4.463秒   服务器环境:Linux  Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2 




0.257秒    服务器环境:Linux  Apache/2.2 



0.744秒  Linux  Apache     





我们再来看一下国内各大论坛的:






LeadBBS的ASP讨论区版块,帖子数量473130

0.016秒  服务器类型不用检测了,服务器环境:windows server2003无疑




直接翻页至2167页时的执行时间

0.313秒




落伍者论坛资源交流专栏版块,帖子数量9415721 , 940多万!

0.010872秒  服务器环境:Linux+Apache






落伍者论坛资源交流专栏版块直接翻页至999页执行时间

0.949476秒





Discuz官方论坛安装使用版块,帖子数量1274144

0.018436秒  Discuz官方服务器 Linux  nginx/0.6.29    

       事实胜于雄辩!!Wordpress这样的PHP程序,效率连asp+access都差了好几个档次,跟其他大型的php程序更不是在一两个档次。也许你说又是没有开缓存,又是没有生成静态啦,如果一个程序执行效率都不行,日志数量多或访问量大就造成服务不可用的话,再多的插件又有什么用?有兴趣的可以把wordpress导入百万数据试一下,程序执行效率更是慢的让人吃惊。相反其他php博客程序就快的多。提高程序的运行效率难道不是一个优秀的甚至合格的程序员所必须甚至首先考虑的?




另外转一篇详细分析wordpress的效率的文章,这边文章说的更加具体了:
引用内容 引用内容

http://www.21andy.com/blog/20070216/591.html

昨天一个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不是那么好查询的,别没事整天查。



另外一篇:
http://www.21andy.com/blog/20060813/374.html
引用内容 引用内容

受不了Wordpress的速度,今天非要找出个所以然来.
开始!
在wp-config.php中加入

><?php
define('SAVEQUERIES', true); ?>

在模板文件footer.php中加入

><?php
var_dump($wpdb->queries); ?>

修改模板,并卸了所有的PLUGIN,将wp恢复到最简洁状态,然后运行测试.

一共6万文章,首页执行时间在16-30秒左右,分类的列表页执行效率居然高了快7倍,在4秒左右.

来看看执行首页都有哪些查询

19 queries. 16.817 seconds.

array(19) {
[0]=>
array(2) {
[0]=>
string(65) “Select option_value FROM wp_options Where option_name = ’siteurl’”
[1]=>
float(0.000766038894653)
}
[1]=>
array(2) {
[0]=>
string(71) “Select option_name, option_value FROM wp_options Where autoload = ‘yes’”
[1]=>
float(0.00127911567688)
}
[2]=>
array(2) {
[0]=>
string(79) “Select option_value FROM wp_options Where option_name = ‘rewrite_rules’ LIMIT 1″
[1]=>
float(0.000645875930786)
}
[3]=>
array(2) {
[0]=>
string(79) “Select option_value FROM wp_options Where option_name = ‘rewrite_rules’ LIMIT 1″
[1]=>
float(0.000285863876343)
}
[4]=>
array(2) {
[0]=>
string(207) ” Select DISTINCT * FROM wp_posts Where 1=1 AND post_date_gmt <= '2006-08-13 06:41:59' AND (post_status = "publish") AND post_status != "attachment" GROUP BY wp_posts.ID orDER BY post_date DESC LIMIT 0, 50"
[1]=>
float(12.4344360828)
}
[5]=>
array(2) {
[0]=>
string(356) “Select post_id, category_id FROM wp_post2cat Where post_id IN (29271, 550, 33318, 23145, 55913, 15376, 48144, 9332, 42100, 2081, 34849, 21539, 54307, 31042, 20684, 53452, 3023, 35791, 18805, 51573, 2775, 35543, 14502, 47270, 17286, 50054, 20112, 52880, 22078, 54846, 27809, 19048, 51816, 30658, 6829, 39597, 11084, 43852, 29775, 29859, 14854, 47622, 23742, 56510, 11496, 44264, 10043, 42811, 30274, 18221)”
[1]=>
float(0.0330619812012)
}
[6]=>
array(2) {
[0]=>
string(27) “Select * FROM wp_categories”
[1]=>
float(0.000616073608398)
}
[7]=>
array(2) {
[0]=>
string(391) “Select post_id, meta_key, meta_value FROM wp_postmeta Where post_id IN(29271, 550, 33318, 23145, 55913, 15376, 48144, 9332, 42100, 2081, 34849, 21539, 54307, 31042, 20684, 53452, 3023, 35791, 18805, 51573, 2775, 35543, 14502, 47270, 17286, 50054, 20112, 52880, 22078, 54846, 27809, 19048, 51816, 30658, 6829, 39597, 11084, 43852, 29775, 29859, 14854, 47622, 23742, 56510, 11496, 44264, 10043, 42811, 30274, 18221) orDER BY post_id, meta_key”
[1]=>
float(0.000411033630371)
}
[8]=>
array(2) {
[0]=>
string(278) “Select DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM wp_posts Where post_date < '2006-08-13 14:41:21' AND post_date != '0000-00-00 00:00:00' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) orDER BY post_date DESC"
[1]=>
float(1.06055593491)
}
[9]=>
array(2) {
[0]=>
string(86) “Select option_value FROM wp_options Where option_name = ‘kubrick_header_image’ LIMIT 1″
[1]=>
float(0.000422954559326)
}
[10]=>
array(2) {
[0]=>
string(86) “Select option_value FROM wp_options Where option_name = ‘kubrick_header_color’ LIMIT 1″
[1]=>
float(0.000302076339722)
}
[11]=>
array(2) {
[0]=>
string(88) “Select option_value FROM wp_options Where option_name = ‘kubrick_header_display’ LIMIT 1″
[1]=>
float(0.000371932983398)
}
[12]=>
array(2) {
[0]=>
string(45) “Select * FROM wp_users Where ID = ‘1′ LIMIT 1″
[1]=>
float(0.000383138656616)
}
[13]=>
array(2) {
[0]=>
string(64) “Select meta_key, meta_value FROM wp_usermeta Where user_id = ‘1′”
[1]=>
float(0.000432968139648)
}
[14]=>
array(2) {
[0]=>
string(155) “Select COUNT(DISTINCT ID) FROM wp_posts Where 1=1 AND post_date_gmt <= '2006-08-13 06:41:59' AND (post_status = "publish") AND post_status != "attachment""
[1]=>
float(1.02000594139)
}
[15]=>
array(2) {
[0]=>
string(169) ”
Select cat_ID, cat_name, category_nicename, category_description, category_parent, category_count
FROM wp_categories
Where cat_ID > 0
orDER BY cat_name asc”
[1]=>
float(0.00116395950317)
}
[16]=>
array(2) {
[0]=>
string(76) “Select * FROM wp_posts Where post_status = ’static’ orDER BY post_title ASC”
[1]=>
float(0.935003995895)
}
[17]=>
array(2) {
[0]=>
string(278) “Select DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM wp_posts Where post_date < '2006-08-13 14:41:24' AND post_date != '0000-00-00 00:00:00' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) orDER BY post_date DESC"
[1]=>
float(0.997811079025)
}
[18]=>
array(2) {
[0]=>
string(295) ”
Select DISTINCT link_category, cat_name, show_images,
show_description, show_rating, show_updated, sort_order,
sort_desc, list_limit
FROM `wp_links`
LEFT JOIN `wp_linkcategories` ON (link_category = cat_id)
Where link_visible = ‘Y’
AND list_limit <> 0
orDER BY cat_name ”
[1]=>
float(0.00177693367004)
}
}

很明显,第一个加粗部份的sql语句,居然执行了12秒!我汗!!!!
再来看看分类列表页都执行了些啥样的sql

19 queries. 3.430 seconds. 

array(19) {
[0]=>
array(2) {
[0]=>
string(65) “Select option_value FROM wp_options Where option_name = ’siteurl’”
[1]=>
float(0.000646114349365)
}
[1]=>
array(2) {
[0]=>
string(71) “Select option_name, option_value FROM wp_options Where autoload = ‘yes’”
[1]=>
float(0.00108289718628)
}
[2]=>
array(2) {
[0]=>
string(79) “Select option_value FROM wp_options Where option_name = ‘rewrite_rules’ LIMIT 1″
[1]=>
float(0.000606060028076)
}
[3]=>
array(2) {
[0]=>
string(79) “Select option_value FROM wp_options Where option_name = ‘rewrite_rules’ LIMIT 1″
[1]=>
float(0.000309944152832)
}
[4]=>
array(2) {
[0]=>
string(27) “Select * FROM wp_categories”
[1]=>
float(0.000545978546143)
}
[5]=>
array(2) {
[0]=>
string(32) “Select cat_ID FROM wp_categories”
[1]=>
float(0.000543117523193)
}
[6]=>
array(2) {
[0]=>
string(292) ” Select DISTINCT * FROM wp_posts LEFT JOIN wp_post2cat ON (wp_posts.ID = wp_post2cat.post_id) Where 1=1 AND (category_id = 35) AND post_date_gmt <= '2006-08-13 06:43:59' AND (post_status = "publish") AND post_status != "attachment" GROUP BY wp_posts.ID orDER BY post_date DESC LIMIT 0, 50"
[1]=>
float(0.0346350669861)
}
[7]=>
array(2) {
[0]=>
string(363) “Select post_id, category_id FROM wp_post2cat Where post_id IN (41073, 41074, 41058, 41053, 41066, 40988, 41070, 40992, 41034, 41056, 41020, 40996, 41051, 40989, 41023, 41017, 40991, 41039, 41071, 40993, 41077, 41031, 41030, 41062, 41002, 41025, 41028, 41021, 41047, 40990, 41008, 41061, 41042, 41033, 41052, 41065, 41078, 41076, 41004, 41049, 41043, 41014, 41027, 40998, 41036, 41059, 41050, 41072, 41011, 41069)”
[1]=>
float(0.00174999237061)
}
[8]=>
array(2) {
[0]=>
string(398) “Select post_id, meta_key, meta_value FROM wp_postmeta Where post_id IN(41073, 41074, 41058, 41053, 41066, 40988, 41070, 40992, 41034, 41056, 41020, 40996, 41051, 40989, 41023, 41017, 40991, 41039, 41071, 40993, 41077, 41031, 41030, 41062, 41002, 41025, 41028, 41021, 41047, 40990, 41008, 41061, 41042, 41033, 41052, 41065, 41078, 41076, 41004, 41049, 41043, 41014, 41027, 40998, 41036, 41059, 41050, 41072, 41011, 41069) orDER BY post_id, meta_key”
[1]=>
float(0.000437021255493)
}
[9]=>
array(2) {
[0]=>
string(278) “Select DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM wp_posts Where post_date < '2006-08-13 14:43:36' AND post_date != '0000-00-00 00:00:00' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) orDER BY post_date DESC"
[1]=>
float(1.01349496841)
}
[10]=>
array(2) {
[0]=>
string(86) “Select option_value FROM wp_options Where option_name = ‘kubrick_header_image’ LIMIT 1″
[1]=>
float(0.000421047210693)
}
[11]=>
array(2) {
[0]=>
string(86) “Select option_value FROM wp_options Where option_name = ‘kubrick_header_color’ LIMIT 1″
[1]=>
float(0.00031304359436)
}
[12]=>
array(2) {
[0]=>
string(88) “Select option_value FROM wp_options Where option_name = ‘kubrick_header_display’ LIMIT 1″
[1]=>
float(0.000300168991089)
}
[13]=>
array(2) {
[0]=>
string(45) “Select * FROM wp_users Where ID = ‘1′ LIMIT 1″
[1]=>
float(0.000428915023804)
}
[14]=>
array(2) {
[0]=>
string(64) “Select meta_key, meta_value FROM wp_usermeta Where user_id = ‘1′”
[1]=>
float(0.000426054000854)
}
[15]=>
array(2) {
[0]=>
string(240) “Select COUNT(DISTINCT ID) FROM wp_posts LEFT JOIN wp_post2cat ON (wp_posts.ID = wp_post2cat.post_id) Where 1=1 AND (category_id = 35) AND post_date_gmt <= '2006-08-13 06:43:59' AND (post_status = "publish") AND post_status != "attachment""
[1]=>
float(0.039783000946)
}
[16]=>
array(2) {
[0]=>
string(169) ”
Select cat_ID, cat_name, category_nicename, category_description, category_parent, category_count
FROM wp_categories
Where cat_ID > 0
orDER BY cat_name asc”
[1]=>
float(0.001296043396)
}
[17]=>
array(2) {
[0]=>
string(76) “Select * FROM wp_posts Where post_status = ’static’ orDER BY post_title ASC”
[1]=>
float(0.955458164215)
}
[18]=>
array(2) {
[0]=>
string(278) “Select DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM wp_posts Where post_date < '2006-08-13 14:43:38' AND post_date != '0000-00-00 00:00:00' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) orDER BY post_date DESC"
[1]=>
float(1.03362488747)
}
}



这个分析的够清楚了,真不知道为什么搞这么复杂的查询,有些查询根本不必每次都查,直接放到缓存就可以的。
[本日志由 Admin 于 2008-04-30 12:22 AM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags:
评论: 10 | 引用: 0 | 查看次数: 5739
发表评论
昵 称:
密 码: 游客发言不需要密码.
验证码: 14+6=?
内 容:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册账号.
字数限制 500 字 | UBB代码 关闭 | [img]标签 关闭