【问题标题】:Count votes in subquery or use join - which is faster?在子查询中计算选票或使用连接 - 哪个更快?
【发布时间】:2015-02-05 17:42:57
【问题描述】:

我正在开发一个论坛系统 (mysql),我不确定在检索单个查询帖子、上下投票以及当前用户是否为每个帖子投票时选择哪个路径以获得更好的性能。 第一个选项是这样的:

SELECT posts.post_id, post_content, display_name, 
(SELECT COUNT(post_id) FROM post_votes WHERE post_votes.post_id=posts.post_id AND post_votes.user_id='+user_id+') voted,
(SELECT COUNT(post_id) FROM post_votes WHERE post_votes.post_id=posts.post_id AND up_vote=1) upvotes, 
(SELECT COUNT(post_id) FROM post_votes WHERE post_votes.post_id=posts.post_id AND up_vote=0) downvotes
FROM posts JOIN users ON users.user_id=posts.user_id WHERE parent_id ='+parent_id+' ORDER BY post_id DESC

第二个选项是用 LEFT JOIN 和 count 替换所有 count 子查询。 一种方法比另一种方法有什么优势吗?

编辑:

由于我要检索所有帖子,而不是对帖子进行分组的单行,所以我想出了这个查询(灵感来自from here):

SELECT p.post_id, post_content, display_name,
COALESCE(v.upvotes, 0) AS upvotes, 
COALESCE(v.downvotes, 0) AS downvotes, 
COALESCE(v.voted, 0) AS voted 
FROM posts p 
LEFT JOIN ( 
        SELECT post_id, 
        SUM(vt.up_vote = 1) AS upvotes, 
        SUM(vt.up_vote = 0) AS downvotes, 
        MAX(IF(vt.user_id = ' + user_id + ', vt.up_vote, NULL)) voted 
        FROM post_votes vt 
        GROUP BY vt.post_id
        ) 
        v ON v.post_id = p.post_id 
JOIN users ON users.user_id=p.user_id 
WHERE parent_id =' + parent_id + ' ORDER BY post_id DESC

我在我的演示数据库上运行了这两种解决方案(目前很小,每个表中包含不到 100 行)并且持续时间相同。 问题是从长远来看哪一个会更快。

【问题讨论】:

  • 参考this question
  • 我会选择子查询选项..
  • 你告诉我。双向运行。
  • @raging Bull-thx。这个问题有一个很大的问题,但它取决于它,所以我想就这个特殊情况征求意见。
  • @rahul - 在这种情况下你为什么更喜欢子查询?

标签: mysql performance join subquery


【解决方案1】:

我几乎想不出子查询比连接快的任何事情。

在这种情况下,您甚至不需要加入。在一个查询中完成所有操作:

SELECT 
p.post_id, 
p.post_content, 
u.display_name, 
COUNT(pv.post_id) AS voted,
SUM(pv.up_vote = 1) AS upvotes,
SUM(pv.up_vote = 0) downvotes
FROM posts p
JOIN users u ON u.user_id = p.user_id 
LEFT JOIN post_votes pv ON posts.post_id = pv.post_id AND pv.user_id ='whatever'
WHERE p.parent_id ='+parent_id+' 
GROUP BY p.post_id
ORDER BY p.post_id DESC

SUM() 函数内的pv.up_vote = 'whatever' 返回真或假,1 或 0。这就是我们在这里使用SUM() 函数的原因。瞧,一切尽在一个查询中。

【讨论】:

  • 谢谢。请解释 count(*) 如何在不添加子查询的情况下计算用户是否投票?顺便说一句,反对票应该单独计算,而不是从赞成票中减去。
  • COUNT(*) 只是总行数。如果您只想计算 post_vote 表中的行数,请指定该表中的列名。在我的回答中解决了这个问题。你的第二条评论我不明白。我的答案没有减去任何内容。
  • 好的,我试试。但是我仍然不确定计数器与登录用户的具体关系,而不是与所有投票的关系。第二个问题现在很清楚了
  • 好吧,我假设每一行都是一票。您没有提供有关您的数据的任何信息,我所看到的只是一个查询。想想看。在问题中包含样本数据和期望的结果以及对数据的简短解释总是一个好主意。
  • 在检查了您的解决方案并发现输出是单行之后,我意识到我可能没有很好地解释要求。您的解决方案适用于计算特定父 ID 下的帖子投票数,但我实际上需要的是多行,每个帖子一个。
猜你喜欢
  • 2013-09-23
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 2011-11-13
  • 2011-09-28
  • 2012-11-11
  • 1970-01-01
相关资源
最近更新 更多