(使用MySQL)我有一个视频表(简化):
+---------+-------------+-------------+
| videoID | videoName | videoAuthor |
+---------+-------------+-------------+
| 1 | cool_video1 | rocky |
| 2 | mixingTest2 | sensable |
+---------+-------------+-------------+
和视频评分表,也就是说,每当用户喜欢或不喜欢视频时,都会在videoRatings表中添加/更新一行: 例如,这意味着带有videoID 1的视频有两个喜欢和一个不喜欢。 videoRatings表中的“1”是类似的。 “2”是不喜欢(简化)
+---------------+---------+-------------------+
| videoRatingID | videoID | videoRatingTypeID |
+---------------+---------+-------------------+
| 121 | 1 | 1 |
| 234 | 1 | 1 |
| 290 | 1 | 2 |
+---------------+---------+-------------------+
现在,很简单,我想要做的就是获得大约100,000个视频的得分最高的视频 我自然会这样做:
SELECT Videos.videoID,
COUNT(CASE WHEN videoRatingTypeID =1 THEN 1 ELSE NULL END) AS likes,
COUNT(CASE WHEN videoRatingTypeID =2 THEN 1 ELSE NULL END) AS dislikes
FROM Videos
LEFT JOIN VideoRatings ON VideoRatings.videoID = Videos.videoID
GROUP BY Videos.videoID
ORDER BY likes DESC
但是此查询大约运行半秒钟。这让我担心,当视频表达到> 1mil时,这将更长。 videoRatings表非常小(约40行),视频表约为100,000行。
我在Videos表中有视频ID的索引,在videoID,videoRatingID和videoID + videoRatingID上的复合索引的videoRatings表中有索引
我没有看到更好的方法来做到这一点。我已经阅读了几篇关于通过外部移动订单的帖子。但是当我这样做时:
SELECT * FROM (
SELECT Videos.videoID,
COUNT(CASE WHEN videoRatingTypeID =1 THEN 1 ELSE NULL END) AS likes,
COUNT(CASE WHEN videoRatingTypeID =2 THEN 1 ELSE NULL END) AS dislikes
FROM Videos
LEFT JOIN VideoRatings
GROUP BY Videos.videoID
) tmp
ORDER BY tmp.likes DESC
没有改善。
有什么更好的方法来处理此布局或此查询?谢谢!
答案 0 :(得分:1)
对于真正的可扩展性,我认为您需要一个维护摘要表的解决方案。与此同时,这可能会更快:
select v.videoID,
(select count(*)
from VideoRatings vr
where vr.videoID = v.videoID and
videoRatingTypeId = 1
) as likes,
(select count(*)
from VideoRatings vr
where vr.videoID = v.videoID
videoRatingTypeId = 2
) as dislikes
from Videos v;
请确保您在VideoRatings(videoId, videoRatingTypeId)
上有一个索引(实际上,索引中的类型ID不是那么重要,但它可以提供帮助)。
这将取代整套视频和评分中的group by
,包括索引扫描和小型聚合。只要videoRatings
的索引适合内存,这就会向上扩展。
编辑:
您的视频评分表非常简洁,包含的信息远远少于喜欢和不喜欢的摘要数量。例如,这样的表可能具有评级的日期/时间和进行评级的人。
BUT。您正在通过insert
行向此表添加新的评分。嗯,与update
另一个表(可能是videos
)的信息几乎相同。然后将您当前的表视为历史日志。
使用update
的优点是可以在日志变大时截断日志。现在,您必须保留每个视频的开始时的每个评级。