优化需要1分钟执行的简单查询

时间:2010-12-09 16:45:49

标签: sql mysql query-optimization

我有这个相当简单的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结果:

http://i.min.us/ibeAnM.png

涉及的表格:

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表可以与albumsimages加入,对我来说无关紧要。

edit2:将a.access = 'public'WHERE移动到JOIN确实解决了我的问题,但返回的结果不正确(我从不公开的相册中获取图片), a.access ...WHERE中的JOIN比以前更慢地减慢查询速度。

3 个答案:

答案 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

如果您将连接相册留给用户,则可以返回所有没有用户的相册。不确定你想要哪一个。