MySql使用SUM()结果加速缓慢

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (2444)

有谁知道一种更有效的方法来执行这个查询?

SELECT SQL_CALC_FOUND_ROWS p.*, IFNULL(SUM(v.visits),0) AS visits,
FROM posts AS p 

LEFT JOIN visits_day v ON v.post_id=p.post_id 

GROUP BY post_id 
ORDER BY post_id DESC LIMIT 20 OFFSET 0

visits_day表每个帖子每个用户每天有一条记录。随着表的增长,这个查询非常慢。

我无法添加一个包含总访问次数的列,因为我需要按每天或每周更多访问次数列出帖子等。

有谁知道这个问题的解决方案?

谢谢

CREATE TABLE `visits_day` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `post_id` int(11) NOT NULL,
 `user_id` int(11) NOT NULL,
 `day` date NOT NULL,
 `visits` int(11) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=52302 DEFAULT CHARSET=utf8

CREATE TABLE `posts` (
 `post_id` int(11) NOT NULL AUTO_INCREMENT,
 `link` varchar(300) NOT NULL,
 `date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
 `title` varchar(500) NOT NULL,
 `img` varchar(300) NOT NULL,
 PRIMARY KEY (`post_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1027 DEFAULT CHARSET=utf8
提问于
用户回答回答于

有了SQL_CALC_FOUND_ROWS,查询必须评估所有内容,而不是传递所有行。摆脱它应该是有益的。

要真正接触只有20行,我们需要通过获取WHEREGROUP BYORDER BY用一个单一的指标。否则,我们可能必须触摸所有行,然后对它们进行排序,然后交付20个。明显的指数是(post_id); 我怀疑它已被索引为PRIMARY KEY(post_id)?(如果您SHOW CREATE TABLE在提问时提供,将会有所帮助。)

另一种进行连接并获得所需零结果的方法如下。请注意,它消除了对它的需要GROUP BY

SELECT p.*,
       IFNULL( ( SELECT SUM(v.visits)
                   FROM visits_day
                   WHERE post_id = p.post_id
               ),
            0) AS visits
    FROM posts AS p 
    ORDER BY post_id DESC
    LIMIT 20 OFFSET 0

如果你真的需要计数,那就考虑一下SELECT COUNT(*) FROM posts

ON v.post_id=p.post_id在您的查询,WHERE post_id = p.post_id乞求INDEX(post_id)visits_day。这将大大加快这两个变种。

扫码关注云+社区

领取腾讯云代金券