2009-10-19 7 views
0

Je suis en train de concevoir un projet pour des quiz et des résultats de quizz. J'ai donc deux tables: quizz_result et quizz. le quizz a la clé primaire sur l'ID et le quizz_result a la clé étrangère QUIZZ_ID pour interroger l'identité.Deux jointures à gauche et une requête à un problème de performance MySQL

La requête ci-dessous est conçue pour prendre des quiz publics classés par date avec des informations associées: si l'utilisateur actuel (683735) a répondu à ce quiz et a un résultat valide (> 0).

donc je n'ai cette simple requête avec deux gauche rejoint:

select  
    a.*, 
    COUNT(countt.QUIZZ_ID) SUMFILL 
from 
    quizz a 
    left join quizz_result countt 
    on countt.QUIZZ_ID = a.ID 
group by 
    a.ID 

et les index ajoutés sur ces colonnes: quizz:

ID, (ID, DATE), PUBLIC, (PUBLIC, DATE) 

Et quizz_result:

ID, (QUIZZ_ID, USER_ID), QUIZZ_ID, USER_ID, (QUIZZ_ID, QUIZZ_RESULT_ID) 

Mais quand je fais une requête, cela prend environ une minute. Et j'ai seulement 34k lignes dans QUIZZ_RESULTS et 120 lignes dans la table QUIZZ.

Quand je n'EXPLIQUER sur cette requête, j'obtiens ceci:

SELECT TYPE: simple, possible keys: IDX_PUBLIC,DATE, rows: 34 extra: Using where; Using temporary; Using filesort 
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZZ_RES_RES_QUIZ,IDX_USERID,I..., rows: 1, extra: nothing here 
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZ_RES_RES_QUIZZ,ID_RESULT_ID, rows: 752, extra: Using index 

Et je ne sais pas quoi faire pour optimiser cette requête. Je vois ceci:

Using where; Using temporary; Using filesort 

Mais je ne sais pas comment ce mieux, ou peut-être le nombre de lignes dans la dernière sélection est à hight? 752?

Comment puis-je optimiser cette requête?

EDIT: J'ai mis à jour la requête à celle-ci avec une seule jointure à gauche car elle a le même temps d'exécution long.

EDIT2: J'ai tout supprimé et c'est tout: ce simple choix avec une requête prend 1s à exécuter. Comment l'optimiser?

+0

Essayez de lancer OPTIMIZE TABLE quizz, quizz_result; – Greg

+0

@Greg Merci pour votre conseil. Je l'ai fait mais encore le temps est le même –

Répondre

0

Je l'ai changé à ceci:

select  
    a.*, 
    COUNT(a.ID) SUMFILL 
from 
    quizz a 
    left join quizz_result countt 
    on countt.QUIZZ_ID = a.ID 
group by 
    a.ID 

Et il est bon maintenant.

0

Qu'en est-il d'un index sur (USER_ID, QUIZZ_ID, QUIZZ_RESULT_ID), puisqu'ils sont tous associés?

+0

Je pense que vous avez raison qui devrait aider, mais je l'ai ajouté à cette table, mais malheureusement, les temps sont les mêmes. Alors peut-être que ce serait la prochaine optimisation. Il y a toujours quelque chose de grand et de mauvais dans cette requête –

+0

C'est toujours lent avec seulement une gauche à rejoindre? Je n'ai pas beaucoup d'expérience, mais cela ne me semble pas correct. Y a-t-il beaucoup d'autres requêtes qui prennent beaucoup de temps et qui ne devraient pas l'être?Avez-vous modifié les paramètres du moteur de base de données (threads, mémoire partagée, etc.) par défaut? Je suppose avant cela, vérifiez que vous avez réellement mis en place une restriction de clé étrangère sur quizz_result. – Kev

1

Essayez de retirer certaines de ces conditions supplémentaires de vos jointures. Les déplacer vers la clause where peut parfois aider. En outre, considérez placer les jointures de noyau dans leur propre sous-requête et ensuite limiter cela avec une clause where.

+0

J'essaye mais sans succès peux-tu être plus descriptif? –

+0

Depuis ma réponse originale, votre requête a changé et je ne pense pas que ma réponse soit valable plus longtemps. Jetez un oeil aux index que vous avez sur ces deux tables. Assurez-vous d'avoir des index sur toutes les colonnes que vous rejoignez. Dans la mesure du possible, joignez des valeurs uniques dans chaque table (par exemple, clés primaires et étrangères). –

0

Essayez ceci:

SELECT q.*, 
     (
     SELECT COUNT(*) 
     FROM quizz_results qr 
     WHERE qr.quizz_id = q.id 
     ) AS total_played, 
     (
     SELECT result 
     FROM qr.quizz_id = q.id 
       AND user_id = 683735 
     ) AS current_user_won 
FROM quizz q 
Questions connexes