gpt4 book ai didi

mysql - 优化 mysql 查询(喜欢/不喜欢)

转载 作者:行者123 更新时间:2023-11-29 05:24:12 25 4
gpt4 key购买 nike

我的网站包含用户可以投票的内容片段(喜欢/不喜欢类似于 reddit upvotes)。选择单个内容时,我运行以下子查询来获取喜欢的数量、不喜欢的数量和当前用户的投票。

投票存储在单独的表 {contentId, userId, vote}

SELECT

[... BUNCH OF FIELDS ...]

(SELECT COUNT(*) FROM votes vt WHERE vt.cId = c.contentId AND vote = '.Constants::LIKE.') AS likes,
(SELECT COUNT(*) FROM votes vt WHERE vt.cId = c.contentId AND vote = '.Constants::DISLIKE.') AS dislikes,
COALESCE((SELECT vote FROM votes vt WHERE vt.cId = c.contentId AND userId = '.USER_ID.'), '.Constants::NO_VOTE.') AS myVote

FROM content

[... OTHER STUFF ... ]

是否有更好的方法来实现这一点(组合这些子查询或其他方式)?

最佳答案

就性能而言,那些相关的子查询可以吃掉你的午餐。并且由于 MySQL 处理它们的方式,对于大集合也吞噬你的午餐盒。对于外部查询中返回的每一行,都会执行这些子查询中的每一个。对于大集合来说,这可能会变得非常昂贵。

另一种方法是使用内联 View 具体化所有内容的好恶,然后对其进行连接操作。

但是,这种方法也可能很昂贵,特别是当您只需要对无数行中的少数内容行进行投票“计数”时。通常,外部查询中的谓词也可以合并到内联 View 中,以限制需要检查和返回的行数。

我们想对该内联 View 使用 OUTER 联接,因此它会返回与您的查询等效的结果;当 vote 表中没有匹配的行时,从 content 返回一行。

SELECT [... BUNCH OF FIELDS ...]
, COALESCE(v.likes,0) AS likes
, COALESCE(v.dislikes,0) AS dislikes
, COALESCE(v.myvote,'.Constants::NO_VOTE.') AS myvote
FROM content c
LEFT
JOIN ( SELECT vt.cId
, SUM(vt.vote = '.Constants::LIKE.') AS likes
, SUM(vt.vote = '.Constants::DISLIKE.') AS dislikes
, MAX(IF(vt.userId = '.USER_ID.',vt.vote,NULL)) AS myvote
FROM votes vt
GROUP
BY vt.cId
) v
ON v.cId = c.contentId

[... OTHER STUFF ... ]

请注意,内联 View 查询(别名为 v)将查看 votes 表中的每一行。如果您只需要一个子集,则考虑添加适当的谓词(在 WHERE 子句中或作为另一个表的 JOIN)。您的查询中的 [... OTHER STUFF ...] 没有指示它是从 content 返回几行还是您需要所有行因为您是通过 likes 等方式订购的。

对于从 content 表中选择的少量行,使用相关子查询(如在您的查询中)实际上比具体化一个巨大的内联 View 并对其执行连接操作要快。

哦...对于这两个查询,不用说,votes 表上具有前导列 cId 的适当索引将提高性能。对于内联 View ,您不希望 MySQL 必须对所有这些行执行 filesort 操作来执行 GROUP BY 的开销。对于相关子查询,您希望它们使用索引范围扫描,而不是全扫描。

关于mysql - 优化 mysql 查询(喜欢/不喜欢),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22054530/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com