J'ai profilé certaines requêtes dans une application sur laquelle je travaille, et je suis tombé sur une requête qui récupérait plus de lignes que nécessaire, le jeu de résultats étant réduit dans le code de l'application.Gauche Joignez-vous à la fonction Inner Join?
La modification d'un jointure gauche à une jointure interne a réduit l'ensemble de résultats à ce qui était nécessaire et serait probablement plus performant (puisque moins de lignes sont sélectionnées). En réalité, la requête LEFT JOIN'ed surpassait l'INNER JOIN'ed, prenant la moitié du temps pour se terminer.
LEFT JOIN: (127 lignes au total, la requête a 0,0011 s)
INNER JOIN: (10 lignes au total, la requête a 0,0024 s)
(j'ai couru les requêtes à plusieurs reprises et ce sont des moyennes) .
Courir EXPLIQUEZ sur les deux révèle rien qui explique les différences de performance:
Pour la INNER JOIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE contacts index NULL name 302 NULL 235 Using where
1 SIMPLE lists eq_ref PRIMARY PRIMARY 4 contacts.list_id 1
1 SIMPLE lists_to_users eq_ref PRIMARY PRIMARY 8 lists.id,const 1
1 SIMPLE tags eq_ref PRIMARY PRIMARY 4 lists_to_users.tag_id 1
1 SIMPLE users eq_ref email_2 email_2 302 contacts.email 1 Using where
Pour LEFT JOIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE contacts index NULL name 302 NULL 235 Using where
1 SIMPLE lists eq_ref PRIMARY PRIMARY 4 contacts.list_id 1
1 SIMPLE lists_to_users eq_ref PRIMARY PRIMARY 8 lists.id,const 1
1 SIMPLE tags eq_ref PRIMARY PRIMARY 4 lists_to_users.tag_id 1
1 SIMPLE users eq_ref email_2 email_2 302 contacts.email 1
Et la requête elle-même:
SELECT `contacts`.*, `lists`.`name` AS `group`, `lists`.`id` AS `group_id`, `lists`.`shared_yn`, `tags`.`name` AS `context`, `tags`.`id` AS `context_id`, `tags`.`color` AS `context_color`, `users`.`id` AS `user_id`, `users`.`avatar`
FROM `contacts`
LEFT JOIN `lists` ON lists.id=contacts.list_id
LEFT JOIN `lists_to_users` ON lists_to_users.list_id=lists.id AND lists_to_users.user_id='1' AND lists_to_users.creator='1'
LEFT JOIN `tags` ON tags.id=lists_to_users.tag_id
INNER JOIN `users` ON users.email=contacts.email
WHERE (contacts.user_id='1')
ORDER BY `contacts`.`name` ASC
(La clause dont je parle est la dernière INNER JOIN dans la table 'users')
La requête s'exécute sur une base de données MySQL 5.1, si cela fait une différence.
Est-ce que quelqu'un a une idée de la raison pour laquelle la requête LEFT JOIN'ed surpasse l'INNER JOIN'ed dans ce cas? En raison de la suggestion de Tomalak que les petites tables que j'utilise rendaient INNER JOIN plus complexe, j'avais créé une base de données de test avec quelques données fictives. La table 'users' contient 5 000 lignes et la table de contacts environ 500 000 lignes. Les résultats sont les mêmes (aussi les timings n'ont pas changé ce qui est surprenant quand on considère que les tableaux sont beaucoup plus gros maintenant). J'ai également lancé ANALYZE et OPTIMIZE sur la table de contacts. N'a pas fait de différence discernable.
Avez-vous essayé de placer la jointure intérieure en premier? –
J'ai, il accélère cette requête de 20%, mais toujours plus lent que LEFT JOIN –
Essayez de construire chaque requête de manière séquentielle (joindre une table, mesurer, joindre la suivante, etc.) Peut-être cela vous aide à déterminer la lenteur . – Tomalak