Bonjour,
J'ai un peu de mal à comprendre la logique du moteur de MariaDB (que je suppose similaire à MySQL) dans une requête... J'ai pourtant la nette impression que ma requête R3 devrait prendre grosso modo le temps de R1 + le temps de R2, et pourtant...
Ne tremblez pas devant les STRAIGHT_JOIN et autres FORCE_INDEX, c'est pour me simplifier la vie car MariaDB optimisait mal ma requête dans certaines conditions et cela m'a permit, jusqu'à peu, de conserver d'excellentes perfs. Bref !
Je précise que j'ai viré le query_cache, je vous donne les perfs moyennes.
R1 : effectuée en 1.27s
R2 : Comme R1 mais je vire ce qui concerne la jointure dl2 ainsi que le GROUP_CONCAT associé dans le SELECT, executée en 0.83s
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 SELECT STRAIGHT_JOIN d.*, UNIX_TIMESTAMP(d.rappel_date) rappel_date_ts, IF(dc.num_com, MD5(CONCAT(dc.num_com, 'commandematnat007')), NULL) c_hash, dc.num_com, cl.mail, cl.nom, cl.prenom, if (cl.cp_livraison != '', cl.cp_livraison, cl.cp) AS cp, cl.cp_livraison, cl.societe, u.nom AS nom_user, u.prenom AS prenom_user, COUNT(co.datetime) as vue_nb, MAX(co.datetime) as vue_lastdate, MAX(UNIX_TIMESTAMP(co.datetime)) as vue_lastdate_ts, MAX(co2.datetime) as relance_lastdate, MAX(UNIX_TIMESTAMP(co2.datetime)) as relance_lastdate_ts, GROUP_CONCAT(DISTINCT dl.date_depart SEPARATOR ';') l_list, GROUP_CONCAT(DISTINCT dl2.date_recpt SEPARATOR ';') l_list_2, GROUP_CONCAT(DISTINCT dpt2.id_produit SEPARATOR ';') l_prod FROM devis d INNER JOIN client cl ON cl.id_client=d.id_client INNER JOIN user u ON u.id_user=d.id_user LEFT JOIN devis_commande dc ON dc.num_devis=d.id LEFT JOIN devis_comment co FORCE INDEX FOR JOIN (id_devis) ON co.type='clic' AND co.id_devis=d.id LEFT JOIN devis_comment comc FORCE INDEX FOR JOIN (id_devis) ON comc.type='clic' AND comc.id_devis=d.id LEFT JOIN devis_comment co2 FORCE INDEX FOR JOIN (id_devis) ON (co2.tel IN ('repondeur', 'eu') OR co2.envoi_email=1) AND co2.id_devis=d.id LEFT JOIN contenu_devis dpt2 FORCE INDEX FOR JOIN (id_devis) ON dpt2.id_devis=d.id LEFT JOIN devis_livraison dl FORCE INDEX FOR JOIN (devis_id) ON dl.devis_id=d.id LEFT JOIN devis_livraison dl2 FORCE INDEX FOR JOIN (devis_id) ON dl2.devis_id=d.id AND (dl2.date_depart IS NULL OR dl2.date_depart='0000-00-00') WHERE d.id IN (35087, 35110, 35110, 34736, 34923, 35059, 25573, 34066, 34362, 35112, 34801, 34997, 35081, 35087, 35110, 35076, 34371, 34893, 34981, 35011, 35078, 33803, 33803, 35129, 35129, 35082, 35132, 34473, 34173, 35103, 35134, 35134, 34187, 34751, 35036, 34731, 35103) GROUP BY d.id LIMIT 0,20
R3 : Complémentaire à R2, on prend les tables principales, on vire tout ce qui est potentiellement lourd à jointer excepter dl2 : exécutée en 0.0025s
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 SELECT STRAIGHT_JOIN d.*, UNIX_TIMESTAMP(d.rappel_date) rappel_date_ts, IF(dc.num_com, MD5(CONCAT(dc.num_com, 'commandematnat007')), NULL) c_hash, dc.num_com, cl.mail, cl.nom, cl.prenom, if (cl.cp_livraison != '', cl.cp_livraison, cl.cp) AS cp, cl.cp_livraison, cl.societe, u.nom AS nom_user, u.prenom AS prenom_user, COUNT(co.datetime) as vue_nb, MAX(co.datetime) as vue_lastdate, MAX(UNIX_TIMESTAMP(co.datetime)) as vue_lastdate_ts, MAX(co2.datetime) as relance_lastdate, MAX(UNIX_TIMESTAMP(co2.datetime)) as relance_lastdate_ts, GROUP_CONCAT(DISTINCT dl.date_depart SEPARATOR ';') l_list, GROUP_CONCAT(DISTINCT dpt2.id_produit SEPARATOR ';') l_prod FROM devis d INNER JOIN client cl ON cl.id_client=d.id_client INNER JOIN user u ON u.id_user=d.id_user LEFT JOIN devis_commande dc ON dc.num_devis=d.id LEFT JOIN devis_comment co FORCE INDEX FOR JOIN (id_devis) ON co.type='clic' AND co.id_devis=d.id LEFT JOIN devis_comment comc FORCE INDEX FOR JOIN (id_devis) ON comc.type='clic' AND comc.id_devis=d.id LEFT JOIN devis_comment co2 FORCE INDEX FOR JOIN (id_devis) ON (co2.tel IN ('repondeur', 'eu') OR co2.envoi_email=1) AND co2.id_devis=d.id LEFT JOIN contenu_devis dpt2 FORCE INDEX FOR JOIN (id_devis) ON dpt2.id_devis=d.id LEFT JOIN devis_livraison dl FORCE INDEX FOR JOIN (devis_id) ON dl.devis_id=d.id WHERE d.id IN (35087, 35110, 35110, 34736, 34923, 35059, 25573, 34066, 34362, 35112, 34801, 34997, 35081, 35087, 35110, 35076, 34371, 34893, 34981, 35011, 35078, 33803, 33803, 35129, 35129, 35082, 35132, 34473, 34173, 35103, 35134, 35134, 34187, 34751, 35036, 34731, 35103) GROUP BY d.id LIMIT 0,20
Suis-je contraint d’exécuter deux requêtes ? C'est assez problématique, car le moteur de recherche associé comporte de nombreux filtres et je devrais passer du temps à redécouper tout ce qui est long...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 SELECT STRAIGHT_JOIN d.*, UNIX_TIMESTAMP(d.rappel_date) rappel_date_ts, cl.mail, cl.nom, cl.prenom, if (cl.cp_livraison != '', cl.cp_livraison, cl.cp) AS cp, cl.cp_livraison, cl.societe, u.nom AS nom_user, u.prenom AS prenom_user, GROUP_CONCAT(DISTINCT dl2.date_recpt SEPARATOR ';') l_list_2 FROM devis d INNER JOIN client cl ON cl.id_client=d.id_client INNER JOIN user u ON u.id_user=d.id_user LEFT JOIN devis_livraison dl2 FORCE INDEX FOR JOIN (devis_id) ON dl2.devis_id=d.id AND (dl2.date_depart IS NULL OR dl2.date_depart='0000-00-00') WHERE d.id IN (35087, 35110, 35110, 34736, 34923, 35059, 25573, 34066, 34362, 35112, 34801, 34997, 35081, 35087, 35110, 35076, 34371, 34893, 34981, 35011, 35078, 33803, 33803, 35129, 35129, 35082, 35132, 34473, 34173, 35103, 35134, 35134, 34187, 34751, 35036, 34731, 35103) GROUP BY d.id LIMIT 0,20
Aussi, et surtout, quelqu'un a-t-il une explication sur ces écarts de temps de recherche ? Je pensais comprendre la façon de fonctionner de MySQL et sur ce coup, j'avoue que je perds pied...
Partager