Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1445 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [MySQL] Besoin d'aide pour optimiser une requête

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[MySQL] Besoin d'aide pour optimiser une requête

n°2024048
mv1975
Posté le 21-09-2010 à 10:01:34  profilanswer
 

Bonjour,
 
Je gère un agenda avec des fiches contacts. Je souhaite récupérer le nombre de contacts ayant un rendez-vous entre le 01/08 et le 31/08 pour la première fois depuis 3 ans.
J'ai fait cette requête :

SELECT COUNT(DISTINCT(personne_id)) FROM wcal_events w
WHERE     id_user=55
      AND eventdate BETWEEN '2010-08-01' AND '2010-08-31'
      AND personne_id != 0
      AND event_etat = 5
      AND faut_id = 58
      AND personne_id NOT IN (SELECT personne_id
                              FROM wcal_events
                              WHERE     id_user=55
                                    AND eventdate BETWEEN SUBDATE(w.eventdate,INTERVAL 3 YEAR) AND SUBDATE(w.eventdate,INTERVAL 1 DAY)
                                    AND personne_id != 0
                                    AND event_etat IN (4,5)
                                    AND faut_id=58
                              GROUP BY personne_id);


Mais elle est longue à s'exécuter, et j'ai cherché d'autres solutions sans résultat efficace ... Quelqu'un pourrait-il m'aider ou me conseiller quelque-chose pour optimiser cela ? je pense que le problème vient de la sous-sélection qui est recalculée à chaque fois ... mais comment faire autrement ?
 
MERCI !!!!

mood
Publicité
Posté le 21-09-2010 à 10:01:34  profilanswer
 

n°2024534
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 22-09-2010 à 16:31:44  profilanswer
 

déjà, as tu des indexes sur tous les champs présents dans les clauses WHERE ?

n°2024535
esox_ch
Posté le 22-09-2010 à 16:35:48  profilanswer
 

Surtout sur eventdate :bounce:


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
n°2024683
rufo
Pas me confondre avec Lycos!
Posté le 23-09-2010 à 13:50:22  profilanswer
 

Perso, je mettrais la sous-requête dans le FROM pour en faire une table temporaire...


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2024692
esox_ch
Posté le 23-09-2010 à 13:57:22  profilanswer
 

rufo a écrit :

Perso, je mettrais la sous-requête dans le FROM pour en faire une table temporaire...


 
A tiens, on y gagne en perf à faire ça? J'ai toujours cru que ça devenait intéressant si on lançait souvent la même requête, mais pas si on lançais des requêtes différentes (par exemple s'il change régulièrement le id_user dans son cas). Que ça va d'une certaine manière dans le même sens que les requêtes préparées.  :bounce:


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
n°2024695
rufo
Pas me confondre avec Lycos!
Posté le 23-09-2010 à 14:07:51  profilanswer
 

Ca dépend de l'utilisation. Là, sa sous-requête est exécutée pour chaque ID de personne. En la mettant dans le FROM et en lui donnant un nom (temporaire), elle ne sera exécutée qu'une fois... Ca devrait donc faire gagner du temps, non?
 
Après, voir avec NOT EXISTS si ça améliore les perfs : http://dev.mysql.com/doc/refman/5. [...] eries.html


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2024698
esox_ch
Posté le 23-09-2010 à 14:12:26  profilanswer
 

Oui mais il me semble que justement il me semble que la 1ère fois qu'elle sera exécutée, elle sera bien plus lente car demandera la création de la table. Donc on y gagnerait seulement si exactement la même requête était exécutée souvent. Là encore, je suis loin d'être un DBA expert.
Concernant l'histoire de NOT EXISTS, je me rappelle avoir vu qqn qui à benché ça sur ce forum récemment et que ça dépendait pas mal de SGDB et de plusieurs autres params. La encore, le mieux est de voir si un DBA passe par là :D


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
n°2024700
Oliiii
Posté le 23-09-2010 à 14:32:04  profilanswer
 

Ca doit pouvoir se faire assez faciment en remplacant le NOT EXIST avec un LEFT JOIN.
Il faut réecrire la query mais pour ca il me faudrai des donnée en exemple et la structure de la table ... et un truc a bouffer :)
 
A vue de nez ca devrai donner un truc comme ca:

Code :
  1. SELECT COUNT(DISTINCT(w.personne_id))
  2. FROM wcal_events w
  3.     LEFT JOIN wcal_events w2 ON w.personne_id = w2.personne_id
  4.                                 AND w2.id_user=55
  5.                                 AND w2.eventdate BETWEEN SUBDATE(w.eventdate,INTERVAL 3 YEAR) AND SUBDATE(w.eventdate,INTERVAL 1 DAY)
  6.                                 AND w2.personne_id != 0
  7.                                 AND w2.event_etat IN (4,5)
  8.                                 AND w2.faut_id=58
  9. WHERE w.id_user=55
  10.     AND w.eventdate BETWEEN '2010-08-01' AND '2010-08-31'
  11.     AND w.personne_id != 0
  12.     AND w.event_etat = 5
  13.     AND w.faut_id = 58
  14.     AND w2.personne_id IS NULL


 
C'est pas testé vu que j'ai que sql server ici (et que c'est pas du t-sql) et j'ai pas de données de tests.
C'est probablement optimisable aussi, c'est juste pour essayer de mettre l'op sur la voie...

n°2024702
rufo
Pas me confondre avec Lycos!
Posté le 23-09-2010 à 14:46:19  profilanswer
 

C'est pour ça qu'il faut faire des tests. mv1975, tu peux aussi utiliser la commande EXPLAIN histoire de voir déjà quels index sont utilisés et si y'a des tables temporaires qui sont créées.  
Tu peux gagner aussi en perfs en tunant Mysql. Ce script peut aider à faire un diagnostic :http://mysqltuner.pl/mysqltuner.pl


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2024703
rufo
Pas me confondre avec Lycos!
Posté le 23-09-2010 à 14:47:41  profilanswer
 

Oliiii a écrit :

Ca doit pouvoir se faire assez faciment en remplacant le NOT EXIST avec un LEFT JOIN.
Il faut réecrire la query mais pour ca il me faudrai des donnée en exemple et la structure de la table ... et un truc a bouffer :)
 
A vue de nez ca devrai donner un truc comme ca:

Code :
  1. SELECT COUNT(DISTINCT(w.personne_id))
  2. FROM wcal_events w
  3.     LEFT JOIN wcal_events w2 ON w.personne_id = w2.personne_id
  4.                                 AND w2.id_user=55
  5.                                 AND w2.eventdate BETWEEN SUBDATE(w.eventdate,INTERVAL 3 YEAR) AND SUBDATE(w.eventdate,INTERVAL 1 DAY)
  6.                                 AND w2.personne_id != 0
  7.                                 AND w2.event_etat IN (4,5)
  8.                                 AND w2.faut_id=58
  9. WHERE w.id_user=55
  10.     AND w.eventdate BETWEEN '2010-08-01' AND '2010-08-31'
  11.     AND w.personne_id != 0
  12.     AND w.event_etat = 5
  13.     AND w.faut_id = 58
  14.     AND w2.personne_id IS NULL


 
C'est pas testé vu que j'ai que sql server ici (et que c'est pas du t-sql) et j'ai pas de données de tests.
C'est probablement optimisable aussi, c'est juste pour essayer de mettre l'op sur la voie...


 
Bien vu le coup du left join à la place du not exits ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
mood
Publicité
Posté le 23-09-2010 à 14:47:41  profilanswer
 

n°2025588
mv1975
Posté le 28-09-2010 à 10:01:10  profilanswer
 

Je reviens tout juste après un arrêt forcé ... Et je découvre avec grand plaisir toutes ces réponses !! Un grand merci à vous tous !!
 
Je peux difficilement vous sortir des données, je travaille sur une copie de données internes à l'entreprise où je travaille, et je ne peux donc pas me permettre de faire sortir ces infos. :/
 
En tout cas, je vais digérer tous vos posts afin d'en sortir quelque chose de super (j'en suis sur).
 
Encore un grand merci !! :)


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [MySQL] Besoin d'aide pour optimiser une requête

 

Sujets relatifs
Aide sur une REGEX C# svpRequête en fonction d'un choix
MySql tres sensible aux surchages et aux requetes simultaneesTomcat et filtre de requête et classloader
Besoin pour agrandir photo au passage de la souris[C++] Demande d'aide pour le portage de PSgroove sur STM8S
[MySQL] Presenter des donnees en ligne en colonneaide regex svp
[mysql] SELECT puis UPDATE du SELECT en une requete 
Plus de sujets relatifs à : [MySQL] Besoin d'aide pour optimiser une requête


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR