复杂的sql,当查询具有order by子句时运行速度极慢

时间:2010-04-22 06:26:10

标签: mysql sql select

我有以下需要使用的复杂查询。当我运行它时,需要30到40秒。但是如果我删除order by子句,则返回结果需要0.0317秒,这与30秒或40秒相比非常快。

select DISTINCT media.*
        , username 
from album as album
     , album_permission as permission
      , user as user, media as media
where ((media.album_id = album.album_id 
        and album.private = 'yes' 
        and album.album_id = permission.album_id 
        and (permission.email = '' or permission.user_id = '') ) 
or (media.album_id = album.album_id 
      and album.private = 'no' ) 
or media.album_id = '0' ) 
and media.user_id = user.user_id
and media.media_type = 'video'
order by media.id DESC 
LIMIT 0,20  

order by上的ID是主键,也是索引。所以我不知道是什么问题。

我还有专辑和专辑权限表,只是为了检查媒体是公共还是私有,如果是私有的,那么检查用户是否拥有权限。我想也许这会导致问题。如果我在子查询中这样做会更好吗?也有人可以帮我写那个子查询,如果这是解决方案?如果你不能写出来,至少告诉我。我真的对这个问题发疯了。

解决方案可能

是的,我认为子查询是最好的解决方案,因为以下查询运行在0.0022秒。但我不确定专辑的验证是否准确,请检查。

select media.*, username 
from media as media
      , user as user
where  media.user_id = user.user_id 
and media.media_type = 'video'
and media.id in 
    (select media2.id
    from     media as media2
            , album as album
            , album_permission as permission
     where ((media2.album_id = album.album_id  
             and album.private = 'yes'
             and album.album_id = permission.album_id 
            and (permission.email = '' 
                 or permission.user_id = ''))
             or (media.album_id = album.album_id 
                   and album.private = 'no' ) 
              or media.album_id = '0' ) 
     and media.album_id = media2.album_id )            
order by media.id DESC
LIMIT 0,20   

1 个答案:

答案 0 :(得分:1)

如果没有ORDER BY子句,请使用EXPLAIN确定更快的原因:

http://dev.mysql.com/doc/refman/5.1/en/using-explain.html

我建议用ANSI连接语法重写查询。这可能有助于提高性能。像这样:

select DISTINCT media.*
        , username 
from album as album
  inner join media as media on media.album_id = album.album_id
  inner join user as user on media.user_id = user.user_id
  left outer join album_permission as permission on album.album_id = permission.album_id
where ((album.private = 'yes' 
        and (permission.email = '' or permission.user_id = '') ) 
or album.private = 'no' 
or media.album_id = '0' ) 
and media.media_type = 'video'
order by media.id DESC 
LIMIT 0,20  

您还可以将查询分成2个或3个不同的查询,并将它们联合起来以避免外部联接。