par
Hubert Roksor » 03 mars 2007, 09:56
EXPLAIN nous donne toutes sortes d'informations très intéressantes. Premièrement, comme je m'en doutais la table "boosters" apparait en premier alors que dans ta requête elle apparait en troisième position. C'est parce que MySQL a été assez intelligent pour comprendre que tu t'étais trompé de jointures et surtout d'ordre pour les tables.
Ta requête originale:
Code : Tout sélectionner
SELECT *
FROM Cartes
LEFT JOIN Versions USING (Numero_Carte)
LEFT JOIN Boosters USING (Numero_Booster)
WHERE Boosters.Numero_Booster = 202
ORDER BY Reference_Carte ASC
Je te conseille de relire le manuel au sujet des jointures LEFT JOIN. Le principe de cette jointure est de lire les enregistrements de la table de "gauche" puis d'y ajoindre les enregistrements correspondants de la table de droite à chaque fois que cela est possible. Ta requête telle qu'elle est formulée voudrait dire "lis toute la table de cartes, puis toute la table de versions, puis essaie de voir ce que tu peux faire avec les boosters". L'autre truc important avec LEFT JOIN c'est que s'il n'y a pas de correspondance possible, l'enregistrement est renvoyé avec des NULL à la place des valeurs, alors qu'une jointure [INNER] JOIN éliminerait simplement l'enregistrement. Dans cet exemple, puisque la table "boosters" apparait dans la clause WHERE, le LEFT JOIN fonctionne comme un JOIN et MySQL le remplace discrètement car les "INNER JOIN" sont généralement plus performants que les "OUTER JOIN" (LEFT JOIN / etc...)
À part ça, qu'est-ce qu'on apprend d'
EXPLAIN ? On voit beaucoup de "ALL" dont le manuel dit
ALL
Une analyse complète de la table sera faîte pour chaque combinaison de lignes issue des premières tables. Ce n'est pas bon si la première table n'est pas une jointure de type const et c'est très mauvais dans les autres cas. Normalement vous pouvez éviter ces situations de ALL en ajoutant des index basée sur des parties de colonnes.
Il te faut donc ajouter des indices sur les colonnes qui servent à faire la jointure. L'embêtant c'est que d'après ta requête je ne sais même pas quelles sont ces colonnes...

Si "Numero_Carte" sert à identifier de façon unique un enregistrement alors l'index devrait être de type "PRIMARY". Si un index PRIMARY existe déjà alors utilise "UNIQUE". Dans tous les autres cas, un INDEX simple suffira. Pour le reste il faudrait que tu postes un schéma simplifié de tes tables ou que tu expliques comment les enregistrements sont joints entre eux. Comment joins-tu les boosters aux cartes? les cartes aux versions?
PS: à quelle table appartient Reference_Carte au fait ?
EXPLAIN nous donne toutes sortes d'informations très intéressantes. Premièrement, comme je m'en doutais la table "boosters" apparait en premier alors que dans ta requête elle apparait en troisième position. C'est parce que MySQL a été assez intelligent pour comprendre que tu t'étais trompé de jointures et surtout d'ordre pour les tables.
Ta requête originale:
[code]SELECT *
FROM Cartes
LEFT JOIN Versions USING (Numero_Carte)
LEFT JOIN Boosters USING (Numero_Booster)
WHERE Boosters.Numero_Booster = 202
ORDER BY Reference_Carte ASC[/code]
Je te conseille de relire le manuel au sujet des jointures LEFT JOIN. Le principe de cette jointure est de lire les enregistrements de la table de "gauche" puis d'y ajoindre les enregistrements correspondants de la table de droite à chaque fois que cela est possible. Ta requête telle qu'elle est formulée voudrait dire "lis toute la table de cartes, puis toute la table de versions, puis essaie de voir ce que tu peux faire avec les boosters". L'autre truc important avec LEFT JOIN c'est que s'il n'y a pas de correspondance possible, l'enregistrement est renvoyé avec des NULL à la place des valeurs, alors qu'une jointure [INNER] JOIN éliminerait simplement l'enregistrement. Dans cet exemple, puisque la table "boosters" apparait dans la clause WHERE, le LEFT JOIN fonctionne comme un JOIN et MySQL le remplace discrètement car les "INNER JOIN" sont généralement plus performants que les "OUTER JOIN" (LEFT JOIN / etc...)
À part ça, qu'est-ce qu'on apprend d'[url=http://dev.mysql.com/doc/refman/5.0/fr/explain.html]EXPLAIN[/url] ? On voit beaucoup de "ALL" dont le manuel dit
[quote]ALL
Une analyse complète de la table sera faîte pour chaque combinaison de lignes issue des premières tables. Ce n'est pas bon si la première table n'est pas une jointure de type const et c'est très mauvais dans les autres cas. Normalement vous pouvez éviter ces situations de ALL en ajoutant des index basée sur des parties de colonnes.[/quote]
Il te faut donc ajouter des indices sur les colonnes qui servent à faire la jointure. L'embêtant c'est que d'après ta requête je ne sais même pas quelles sont ces colonnes... :? Si "Numero_Carte" sert à identifier de façon unique un enregistrement alors l'index devrait être de type "PRIMARY". Si un index PRIMARY existe déjà alors utilise "UNIQUE". Dans tous les autres cas, un INDEX simple suffira. Pour le reste il faudrait que tu postes un schéma simplifié de tes tables ou que tu expliques comment les enregistrements sont joints entre eux. Comment joins-tu les boosters aux cartes? les cartes aux versions?
PS: à quelle table appartient Reference_Carte au fait ?