我想知道是否有办法加快多个子查询排序的mysql查询。
在音乐相关网站上,用户可以喜欢不同的东西,如艺术家,歌曲,专辑等。这些“喜欢”都存储在同一个表格中。现在我想显示一个由用户朋友和所有用户按“喜欢”的数量排序的艺术家列表。我想展示所有艺术家,也包括那些根本没有喜欢的人。
我有以下查询:
SELECT `artists`.*,
// friend likes
(SELECT COUNT(*)
FROM `likes`
WHERE like_type = 'artist'
AND like_id = artists.id
AND user_id IN (1,2,3,4, etc) // ids of friends
GROUP BY like_id
) AS `friend_likes`,
// all likes
(SELECT COUNT(*)
FROM `likes`
WHERE like_type = 'artist'
AND like_id = artists.id
GROUP BY like_id
) AS `all_likes`
FROM artists
ORDER BY
friend_likes DESC,
all_likes DESC,
artists.name ASC
对于具有2000行的艺术家表格,查询需要±1.5秒。随着桌子变得越来越大,我担心这会花费更长的时间。我尝试使用JOINS似乎无法使其工作,因为子查询包含WHERE语句。
非常感谢任何正确方向的想法!
答案 0 :(得分:3)
尝试使用JOIN
而不是子查询:
SELECT
artists.*, -- do you really need all this?
count(user_id) AS all_likes,
sum(user_id IN (1, 2, 3, 4)) AS friend_likes
FROM artists a
LEFT JOIN likes l
ON l.like_type = 'artist' AND l.like_id = a.id
GROUP BY a.id
ORDER BY
friend_likes DESC,
all_likes DESC,
artists.name ASC;
如果这不能使查询更快,请尝试添加索引,或考虑选择更少的字段。
答案 1 :(得分:0)
你需要稍微分解一下,看看时间在哪里。你绝对正确,2000行1.5秒不能很好地扩展。我怀疑你需要看看索引和外键关系。分别查看每个计数/分组查询,以便最好地进行调整,然后重新组合。
答案 2 :(得分:0)
尝试使用内联IF()进行查询并浏览表/ join ONCE
SELECT STRAIGHT_JOIN
artists.*
, LikeCounts.AllCount
, LikeCounts.FriendLikeCount
FROM
(SELECT
like_id
, count(*) AllCount
, sum( If( User_id in ( 1, 2, 3, 4 ), 1, 0 ) as FriendLikeCount
FROM
friend_likes
WHERE
like_type = 'artist'
GROUP BY
like_id ) LikeCounts
JOIN artists ON LikeCounts.like_id = artists.id
ORDER BY
LikeCounts.FriendLikeCount DESC
, LikeCounts.AllCount DESC
, artists.name ASC