【发布时间】:2014-01-22 22:43:39
【问题描述】:
(使用 MySQL)我有一个视频表(简化):
+---------+-------------+-------------+
| videoID | videoName | videoAuthor |
+---------+-------------+-------------+
| 1 | cool_video1 | rocky |
| 2 | mixingTest2 | sensable |
+---------+-------------+-------------+
还有一个视频评分表,即每次用户喜欢或不喜欢视频时,都会在 videoRatings 表中添加/更新一行: 例如,这意味着 videoID 为 1 的视频有两个喜欢和一个不喜欢。 “1”是 videoRatings 表中的一个。 “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
但是这个查询运行大约半秒。这让我担心,当视频表达到 >100 万时,这会更长。 videoRatings 表非常小(约 40 行),video 表约 100,000 行。
我的 videoID 索引显然在 Videos 表中,并且我的 videoRatings 表中的 videoID、videoRatingID 索引和 videoID+videoRatingID 的复合索引
我没有找到更好的方法来做到这一点。我已经阅读了几篇关于将订单移到外面的帖子。但是当我这样做时:
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
改善为零。
处理此布局或此查询的更好方法是什么?谢谢!
【问题讨论】:
-
您使用的是哪个数据库? MySQL 还是 SQL Server?
-
对不起,编辑说,MySQL
-
如果您需要快速响应,那么我建议您有一个喜欢和不喜欢的汇总表,它使用更新/插入/删除触发器或直接通过现在插入喜欢的存储过程进行维护和不喜欢。
-
因为您的
COUNT是计算值,并且您按这些计算值的计数进行排序,我认为您正在阻止使用索引,并强制扫描和排序。跨度> -
@GordonLinoff,我想过这样做,基本上每次触发喜欢/不喜欢时都会更新喜欢或得分列。所以这将是一个近乎即时的查找(只是按分数排序,没有连接)......但是,我希望还有其他我可以做的事情或者我缺少的其他事情,而不是添加那个分数列。我怀疑这是否真的是最好的方法。
标签: mysql sql performance sql-order-by