我有这个相当简单的SQL查询,但执行时间差不多是一分钟:
SELECT
i.id,
...,
a.id AS albums_id,
...,
u.id AS users_id,
...
FROM
images i
LEFT JOIN albums a ON i.albums_id = a.id
LEFT JOIN users u ON a.users_id = u.id
WHERE
a.access = 'public'
AND i.num_of_views > 0
ORDER BY
i.num_of_views DESC
LIMIT
0, 60
以上查询的EXPLAIN结果:
涉及的表格:
images
(约4,822,000行),albums
(约149,000行),users
(约43,000行)
相关指数:
albums
:access(access,num_of_images,album_time),access_2(access,num_of_images,num_of_all_comments,album_time),users_id(users_id,album_time)
images
:browser_2(num_of_views),albums_id(albums_id,image_order)
所有表格都是InnoDB,在MySql v5.1.47上运行
那么如何将其降低到一秒钟以下呢?
如果您需要任何其他信息,请发表评论。
编辑:users
表可以与albums
或images
加入,对我来说无关紧要。
edit2:将a.access = 'public'
从WHERE
移动到JOIN
确实解决了我的问题,但返回的结果不正确(我从不公开的相册中获取图片), a.access ...
和WHERE
中的JOIN
比以前更慢地减慢查询速度。
答案 0 :(得分:3)
在albums.users_id
上添加索引。我也同意有关a.access = 'public'
的评论。但索引应该有所帮助。
由于上面的密钥存在。尝试调整JOIN
的顺序,即将users
移到相册之上,或者将不同的表格作为主要内容。在极少数情况下,这会有所帮助另外,为了更好地加入albums
,请尝试:
LEFT JOIN albums a ON (i.albums_id = a.id AND a.access = 'public')
根据评论,我会删除尽可能多的LEFT JOIN
。由于我不确定您在结果中需要什么,因此我只会将其显示为albums
。这不仅会降低结果集,还会解决应用过滤器的问题。
JOIN albums a ON (i.albums_id = a.id AND a.access = 'public')
答案 1 :(得分:1)
根据您最近的评论,您应该使用INNER JOIN代替专辑而不是LEFT JOIN。
SELECT
i.id,
...,
a.id AS albums_id,
...,
u.id AS users_id,
...
FROM images i
INNER JOIN albums a ON i.albums_id = a.id
LEFT JOIN users u ON a.users_id = u.id
WHERE a.access = 'public'
AND i.num_of_views > 0
ORDER BY i.num_of_views DESC
LIMIT 0, 60
答案 2 :(得分:1)
我认为这里有一点混乱,因为过滤器可以对LEFT JOIN和INNER JOIN产生影响。
Jan,如果你在查询中想要询问的是“为所有公开的专辑获取所有图像,并获得这些专辑的用户”那么你不想要一个左连接,你想要一个内在的加入。左连接将返回所有相册的所有图像,但它也将返回所有没有匹配相册的图像。您可以添加“和a.id IS NOT NULL”,但这与INNER JOIN相同。
我相信你想要的是以下内容:
SELECT
i.id,
...,
a.id AS albums_id,
...,
u.id AS users_id,
...
FROM images i
INNER JOIN albums a ON i.albums_id = a.id AND a.access = 'public'
INNER JOIN users u ON a.users_id = u.id
WHERE i.num_of_views > 0
ORDER BY i.num_of_views DESC
LIMIT 0, 60
如果您将连接相册留给用户,则可以返回所有没有用户的相册。不确定你想要哪一个。