【发布时间】:2018-11-30 13:11:00
【问题描述】:
我有 MySQL 数据库和 5 个名为 tribes(groups)、posts、posts_to_groups、post_comments 和 posts_votes 的表。
组和帖子之间的关系是 MANY_2_MANY,因此每个帖子可以属于多个组,每个组可以包含 0-* 个帖子。这就是表 posts_to_groups 的作用。
我正在搜索从现在开始的过去 24 小时内发布到该用户关注的组中的 3 个最受欢迎的帖子(通过 posts_to_tribes - MANY_2_MANY 关系的表),并按 (cmets_count + votes_count 的总和) ) DESC
这是我当前的查询:
SELECT DISTINCT
p.post_id,
p.description,
p.link,
p.user_id,
p.total_comments,
p.total_votes,
(SELECT
COUNT(*)
FROM
comments
WHERE
last_edited > DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND post_id = p.post_id) AS comments_count,
(SELECT
COUNT(*)
FROM
posts_votes
WHERE
date_voted > DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND post_id = p.post_id) AS votes_count
FROM
posts p
JOIN
posts_to_tribes pt ON pt.post_id = p.post_id
WHERE
pt.tribe_id IN (3 , 38, 107)
ORDER BY (comments_count + votes_count) DESC , p.last_edited DESC
LIMIT 3;
这个查询非常慢,现在需要 ~500ms。
有什么方法可以重写这个查询来提高性能?
更新:
解释输出:
Tim3880建议的查询:
SELECT
p.post_id,
p.description,
p.link,
p.user_id,
p.total_comments,
p.total_votes,
t.comments_count,
t.votes_count
FROM posts p
JOIN (
SELECT
p.post_id,
(SELECT
COUNT(*)
FROM
comments
WHERE
last_edited > DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND post_id = p.post_id) AS comments_count,
(SELECT
COUNT(*)
FROM
posts_votes
WHERE
date_voted > DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND post_id = p.post_id) AS votes_count
FROM
posts p
JOIN
posts_to_tribes pt ON pt.post_id = p.post_id
WHERE
pt.tribe_id IN (3 , 38, 107)
ORDER BY (comments_count + votes_count) DESC , p.last_edited DESC
LIMIT 3
) t
ON p.post_id = t.post_id
ORDER BY (t.comments_count + t.votes_count) DESC , p.last_edited DESC
现在需要 ~280 毫秒。
解释输出:
【问题讨论】:
-
请将您查询中
EXPLAIN SELECT...的结果与您的表定义一起添加。 -
EXPLAIN输出是什么?您在WHERE条件中使用的列上是否有索引? -
感谢您的 cmets !不幸的是,我现在无法访问此数据库,我将在明天提供此信息。
-
没有执行计划,我们只能猜测。您可以尝试使用 group by post id 重写您的子查询,然后将它们加入外部查询。
-
500 毫秒似乎并不特别慢,尤其是在基础表有大量数据的情况下。你的期望是什么。