MySQL 百万行表上的分组最大性能问题

标签 mysql groupwise groupwise-maximum

我正在尝试找到一种直接的方法来提高非常活跃的论坛的性能,这些论坛有大量的帖子,并且 mysql 无法再在内存中进行表排序,并且似乎没有充分利用索引。

这个简单的查询会查找每个主题中的最新帖子,以便用户确定此后他们是否有任何回复(通过稍后比较 topic_time)

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

简单、平坦的 table 看起来像

post_id | poster_id | topic_id | post_status | post_time | post_text

然而,当有一百万个帖子并且用户本身有数万个帖子时,它的性能就会崩溃。 MySQL 要么不再对内存中的表进行排序,要么有太多行需要扫描。在实际使用中,它可能需要长达 3 秒的时间,恕我直言,这是 Not Acceptable ,因为它会在这段时间内占用 CPU 资源并减慢其他人的速度。

我当然可以对索引进行任意组合,但 mysql 似乎最喜欢使用组合

poster_id + post_time 

因此,它只是从百万个帖子中选择一个用户的 5 万个帖子,然后开始按 topic_id 进行分组并排序。奇怪的是,将 topic_id 添加到索引组合中似乎对性能没有帮助,尽管它可能是索引字段的顺序?

我尝试编写一个等效的 JOIN 来代替,这样我就可以使用多个索引,但我遇到了问题,因为每一侧都必须通过 post_status 和海报进行过滤。

我在想,如果mysql可以首先通过post_time的索引对数据进行排序,然后开始按降序为用户挑选不同的topic_id,那么至少在前几页上会更快。命令。我猜这需要一个子查询,并且不确定 50k 结果子查询是否会更好,仍然需要一个临时表。

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

谢谢您的建议!

<小时/>

添加真实示例并说明:

慢日志

# 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)上添加索引后尝试

关于MySQL 百万行表上的分组最大性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11709712/

相关文章:

mysql - group by 子查询后的内连接优化

mysql - SQL 仅选择列上具有最大值的行

php - [MySql]如何从一个表复制一行到另一个表并填充额外的列?

php - 搜索结果后如何更新库存数量?

mysql - 如何获得表中所有内容的总和?

mysql - FreeBSD MySQL安装后出错

linux - 如何在groupwise中更改多个用户的密码?

sql - 在 SQL 中选择每组最少行

c# - 用于访问 c# 的 'Novell GroupWise' 数据的 API。如果我使用 "gwtapp.dll"或 "GroupWise Web Services"会有什么不同?

mysql - SQL 仅选择列上具有最大值的行