2010-04-22 5 views
2

J'ai une requête complexe suivante que j'ai besoin d'utiliser. Quand je l'exécute, cela prend de 30 à 40 secondes. Mais si je retire l'ordre par la clause, il faut 0,0317 sec pour retourner le résultat, ce qui est vraiment rapide comparer à 30 sec ou 40.sql complexe qui s'exécute extrêmement lent lorsque la requête a ordre par clause

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 

L'id sur order by est la clé primaire qui est indexé aussi. Donc je ne sais pas quel est le problème. J'ai également une table d'autorisation d'album et d'album, juste pour vérifier si le média est public ou privé, si privé puis vérifier si l'utilisateur a la permission ou pas. Je pensais que c'est peut-être la cause du problème. Et si je le faisais en sous-requête, cela fonctionnerait-il mieux? Aussi quelqu'un peut-il m'aider à écrire cette sous-requête, si telle est la solution? Si vous ne pouvez pas l'aider, dites-moi au moins. Je suis vraiment devenir fou avec cette question ..

SOLUTION PEUT-ÊTRE

Oui, je pense que la sous-requête serait la meilleure solution pour cela, parce que la requête suivante fonctionne à 0,0022 secondes. Mais je ne suis pas sûr que la validation d'un album soit exacte ou non, merci de vérifier.

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 
+0

Un très bon Q. Je suis intéressé si quelqu'un peut penser à quelque chose pour cela ... – TheCodeArtist

+2

"S'il vous plaît vérifier" - vous devez vérifier cela par vous-même. Testez les deux requêtes. Est-ce qu'ils retournent les mêmes résultats? – APC

+0

je ne peux pas vérifier sur la validation sur la requête, ils retournent tous les deux le même résultat, mais je dois vérifier sur les albums privés aussi, quelles données ne sont pas encore disponibles .. mais de toute façon je les ajouterai plus tard pourquoi fait ça? Je veux dire que les sous-requêtes sont vraiment plus rapides que la première requête. et je les ai testés tous les deux et le résultat est le même. – Basit

Répondre

1

Utilisez EXPLAIN pour déterminer pourquoi il est plus rapide sans la clause ORDER BY:

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

je recommande la réécriture de la requête avec syntaxe de jointure ANSI aussi. Cela pourrait aider la performance. Quelque chose comme ceci:

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 

Vous pouvez aussi séparer la requête en 2 ou 3 différentes requêtes et UNION ensemble pour éviter la jointure externe.

+0

pouvez-vous me dire pourquoi recommandez-vous cette requête et pas sous-requête. parce que votre requête prend 0,0897 sec et sous-requête prend 0,0016 ou 0,0018 sec à charger. – Basit

+0

Personnellement, je m'attendrais à ce que la sous-requête soit plus rapide car vous n'avez plus besoin du DISTINCT. Comme vous ne renvoyez aucune donnée de l'album à l'aide d'une clause IN, elle est généralement plus rapide. Mais si vous utilisez au moins la version de sous-requête, changez pour les jointures explicites, elles sont préférables pour la maintenance et FAR moins susceptibles de donner accidentellement des résultats incorrects.) Il n'y a aucun intérêt à utiliser des jointures implicites. remplacé il y a 20 ans. – HLGEM

+0

@HLGEM pouvez-vous s'il vous plaît donner un exemple en utilisant des jointures explicites .. exemple avec cette requête – Basit