MySQL GroupWise在一百万行表上的最大绩效问题
-
13-12-2019 - |
题
我正在尝试找到一种直接的方式来提高非常有源论坛的性能,其中有大量的帖子,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)
上添加索引后尝试它。
不隶属于 StackOverflow