在我的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。有什么提示吗?
答案 0 :(得分:1)
确保在post_type
,post_status
和post_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_status
和post_type
设为枚举。还要在排序列(post_date
)上添加单独的索引,因为在多索引中,只有左侧的第一列可以用作单个索引。
答案 3 :(得分:-1)
嗯,这只是猜测,但无论如何:我首先尝试将post_date
放在多列索引中。然后索引应按日期排序,结果排序可以通过遍历索引来完成。如果它真的适用于MySQL,我还没试过。
答案 4 :(得分:-1)
请看http://www.slideshare.net/Eweaver/efficient-pagination-using-mysql。那里的建议基本归结为
COUNT()
(或其表兄SQL_CALC_FOUND ROWS
)来显示行(幻灯片列出了一些UI更改或在单独的字段中聚合,以实现此目的)。LIMIT M, N
使用LIMIT N
(实现此目的的方法非常聪明:例如,如果您的帖子按主键排序 DESC
,然后你可以通过添加一个小于当前页面最后一个元素的主键来获得下一页。编辑: Peter Lang的回答涵盖了第一点,但请注意,如果寻呼机允许在其他列上进行排序,那么索引可能就不够了。