我正在尝试找到一种直接的方式来提高非常有源论坛的性能,其中有大量的帖子,MySQL不能再在内存中排序,似乎没有充分利用索引。< / p>

这个简单的查询在每个主题中找到最新的帖子,以确定它们是否有任何回复(以后通过稍后比较主题)

SELECT p.*, MAX(post_time) as post_time FROM forum_posts AS p   
WHERE p.poster_id = '1' AND p.post_status = '0' 
GROUP BY p.topic_id  
ORDER BY post_time DESC 
LIMIT 50
.

简单,平面表看起来像

post_id | poster_id | topic_id | post_status | post_time | post_text
.

然而,当有一百万个帖子和用户自己有成千上万的帖子时,它的性能崩溃了。 MySQL可以再次在内存中排序表格,或者要扫描太多行。最多可以在RealWorld使用中需要3秒,这是不可接受的imho,因为它在那个时间里飙升了CPU,并将其他人减慢了。

我可以做出任何索引的组合,但MySQL似乎主要喜欢使用

的组合
poster_id + post_time 
.

因此它只需选择一个用户的50k帖子,然后按主题和排序开始分组。奇怪地将主题添加到索引组合中似乎没有帮助性能,但它可能是索引字段的顺序?

我试图编写一个等效的连接,所以我可以使用多个索引,但我遇到了问题的事实:必须由Post_Status和海报过滤。

我认为这将是更快的,至少对于前几页,如果可以通过post_time通过它的索引排序mysql,然后在降序中开始为用户选择不同的主题_ID命令。我想这将需要一个子查询,而不确定50k结果子查询会更好,仍需要临时表。

当然,基本解决方案是增加核心设计,以便还有另一个表,只需为每个主题中的每个用户存储Max Post_time,但除非找不到其他解决方案,否则这太大了。

感谢您的任何建议!


添加realworld示例并解释:

慢日志

# Query_time: 2.751334  Lock_time: 0.000056 Rows_sent: 40  Rows_examined: 48286
SELECT   p.*, MAX(post_time) as post_time FROM forum_posts AS p   WHERE p.poster_id = '2' AND p.post_status = '0' GROUP BY p.topic_id  ORDER BY post_time DESC LIMIT 7000, 40;
.

解释

select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
SIMPLE          p   ref poster_time poster_time 4   const   27072   Using where; Using temporary; Using filesort
.

有帮助吗?

解决方案

首先,修复您的查询以提供确定结果:

SELECT p.topic_id, 
       MAX(post_time) as post_time 
FROM forum_posts AS p   
WHERE p.poster_id = '1' AND p.post_status = '0' 
GROUP BY p.topic_id  
ORDER BY post_time DESC 
  LIMIT 50 ;
.

然后在(post_status, poster_id, topic_id, post_time)上添加索引后尝试它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top