上一篇:IE的box模型显示bug - 下一篇:SEO: 搬家,别忘了用301
版权声明:可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2007/01/02/wordpress-performance-tuning/以及本声明。
Wordpress的效率问题似乎一直是议论的热点,今天来看看其中一条SQL语句的效率。
首先将所有插件禁用,并切换为默认模板。 然后按照《WordPress执行效率问题》这篇文章的方法, 在 wp-config.php 中加入
<?php define('SAVEQUERIES', true); ?>
在模板的 footer.php 中加入
<!-- <?php var_dump($wpdb->queries); ?> -->
访问首页,即可从源代码中看到SQL语句。
执行时间最长的是这一条,花了0.02秒:
SELECT DISTINCT * FROM wp_posts
WHERE 1=1
AND post_date_gmt <= '2007-01-02 07:12:59'
AND (
post_status = 'publish'
OR
post_author = 1
AND post_status != 'draft'
AND post_status != 'static'
)
AND post_status != 'attachment'
GROUP BY wp_posts.ID
ORDER BY post_date DESC
LIMIT 0, 10"
这条语句位于 class.php 的 WP_Query->&get_posts() 函数。
说说这个SQL语句的问题。不妨先来看看 wp_posts 表的结构(省略无关列)。
| 列名 | 类型 | 索引 |
| ID | bigint(20) | PRIMARY |
| post_author | bigint(20) | |
| post_date_gmt | datetime | |
| post_status | enum | INDEX |
| post_name | varchar(200) | INDEX |
首先是关键字 DISTINCT,DISTINCT的作用是去掉重复的数据, 相当于对选择的列进行 GROUP BY。而这条语句中选择了 * 列,包含了主键列 ID, 每行数据必然不相同,因此 DISTINCT 关键字起不到任何作用, 白白浪费一次排序。
其次是 post_date_gmt 和 post_author 上的比较操作。wp_posts表仅有 ID、post_status 和 post_name 列上有索引,对其他列的比较操作使得mysql不得不访问wp_posts表的所有数据, 影响效率。
然后是 post_status 上的不等于的比较。对索引列使用不等于比较, 会导致数据库不能使用索引(索引只能判断等于关系)。 另外显然已经有了 post_status = 'publish' 的条件, 不必再判断 post_status != 'attachment'。
最后是 GROUP BY wp_posts.ID,仍然是对一个不会重复的列进行 GROUP BY, 毫无意义。
如果不考虑功能损失,将这个 SQL 语句优化为下面这样,则仅需花费0.003秒。
SELECT * FROM wp_posts WHERE 1=1 AND post_status = 'publish' ORDER BY post_date DESC LIMIT 0, 10"
使用Apache Bench做测试,优化前平均每个请求的处理时间为 503.125ms,优化后为 478.125ms。
2007-01-03 02:16
To fcicq:
1. 的确如此。我只是单纯从SQL语句角度分析了一下。cache的东西等我学会了再好好研究研究。
(1)原来如此。好像wp在这方面留了插件的接口,大概是某些插件会跟post2cat表连接,为此才用的DISTINCT吧。
重复数据么,post2cat表本来可以用post_id和category_id联合起来做主键,偏偏又增加了一个rel_id,有点画蛇添足。
2007-11-30 16:37
优化得不多啊,大头应该不在这里.
2008-02-18 23:38
学习了,不错的文章

2007-01-02 23:49
重要的反而不在这里.
1 AND post_date_gmt <= ‘2007-01-02 07:12:59′
时间是不能使用cache的罪魁祸首.
2 上面说的
另外显然已经有了 post_status = ‘publish’ 的条件,不必再判断 post_status != ‘attachment’。
这是正确的,呵呵
3 如果不考虑功能损失
功能损失也要看程度.
注意几个问题
(1)如果post2cat表中有重复数据的话,distinct id是必要的.
偶想应该修复重复数据这个问题,而不是直接丢给数据库.
(insert into XXX select distinct A,B from tablename)
(2)时间的问题偶想是应该去掉的.只要你不发狠心写篇未来文章 :)