为旧帖子列表优化WordPress SQL查询

时间:2010-02-21 10:07:58

标签: sql mysql wordpress query-optimization

在我的WordPress网站上,当用户远离帖子列表时,查询最终需要几秒钟。我想把它搞定。这是正在执行的查询:

SELECT SQL_CALC_FOUND_ROWS wp_posts.*
FROM wp_posts
WHERE 1=1
  AND wp_posts.post_type = 'post'
  AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_date DESC
LIMIT 846, 47

表格中约有160k行。这是架构的简化版本:

CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL auto_increment,
  `post_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_status` varchar(20) NOT NULL default 'publish',
  `post_type` varchar(20) NOT NULL default 'post',
  PRIMARY KEY  (`ID`),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8

这是查询的EXPLAIN结果:

id  select_type table   type    possible_keys   key key_len ref rows    Extra   
1   SIMPLE  wp_posts    ref type_status_date        type_status_date        62  const   41519   Using where; Using filesort

理想情况下,我想摆脱filesort。有什么提示吗?

5 个答案:

答案 0 :(得分:1)

确保在post_typepost_statuspost_date上设置索引。

160k行应该不是问题。

答案 1 :(得分:1)

你必须在排序列(post_date)上创建一个索引,没有索引将获取所有160k行,filesorted然后大部分被丢弃。

您可能还想查看更积极的缓存,将结果窗口存储在memcache或类似的缓存引擎中。

有关优化http://www.mysqlperformanceblog.com/2008/09/24/four-ways-to-optimize-paginated-displays/

分页显示的更多提示

答案 2 :(得分:0)

使用OR时,确保在其两侧使用索引。

SELECT SQL_CALC_FOUND_ROWS wp_posts.* # change this to select only columns you need
FROM wp_posts 
WHERE (wp_posts.post_type = 'post' AND wp_posts.post_status = 'publish') or (wp_posts.post_type = 'post' OR wp_posts.post_status = 'private') 
ORDER BY wp_posts.post_date DESC LIMIT 846, 47

我还要将post_statuspost_type设为枚举。还要在排序列(post_date)上添加单独的索引,因为在多索引中,只有左侧的第一列可以用作单个索引。

答案 3 :(得分:-1)

嗯,这只是猜测,但无论如何:我首先尝试将post_date放在多列索引中。然后索引应按日期排序,结果排序可以通过遍历索引来完成。如果它真的适用于MySQL,我还没试过。

答案 4 :(得分:-1)

请看http://www.slideshare.net/Eweaver/efficient-pagination-using-mysql。那里的建议基本归结为

  • 有一个合适的索引可以在 order by子句中使用。
  • 避免使用COUNT()(或其表兄SQL_CALC_FOUND ROWS)来显示行(幻灯片列出了一些UI更改或在单独的字段中聚合,以实现此目的)。
  • 不要使用LIMIT M, N使用LIMIT N(实现此目的的方法非常聪明:例如,如果您的帖子按主键排序 DESC ,然后你可以通过添加一个小于当前页面最后一个元素的主键来获得下一页。

编辑: Peter Lang的回答涵盖了第一点,但请注意,如果寻呼机允许在其他列上进行排序,那么索引可能就不够了。