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

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Aidez moi à optimiser cette requete plize!

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Aidez moi à optimiser cette requete plize!

n°1196048
PETOZAK
Posté le 09-09-2005 à 15:31:03  profilanswer
 

Bonjour à tous,
Je suis en train de réaliser une requete assez conséquente et je suis arrivé au bout de mes compétences en terme d'optimisation, j'ai tout essayé : WHERE, HAVING , sous requetes imbriquées...:
Je suis comme meme passer de 5 minutes à 40 secondes puis à 15 secondes puis à 7 et ce sur un Bi Proc XEON...
Sachant que le client possede un pauvre athlon 1.3...je crains le pire...
Voila ma requete aidez moi :) (le MCD ne sera d'aucune utilité, c'est la syntaxe qui n'est pas optimale je pense...)
 

Code :
  1. SELECT SQL_CALC_FOUND_ROWS DATE_FORMAT( actions.date_recontact, '%d/%m/%Y' ) AS date_recontact, lignes_etape.resultat, contacts.id_contact, contacts.nom, societes_specifiques.topage, societes_specifiques.score_societe, societes.id_societe, script_etapes.groupe_etape, s_est_deplace, operation_a_effectuer, SUBSTRING( actions.heure_recontact, 1, 5 ) AS heure_recontact, societes.nom, actions.id_action, actions.id_contact, contacts.fonction_autre
  2. FROM actions
  3. LEFT JOIN lignes_etape ON actions.resultat = lignes_etape.id_ligne_etape
  4. INNER JOIN contacts ON actions.id_contact = contacts.id_contact
  5. AND contacts.plus_dans_la_soc =0
  6. INNER JOIN contacts_specifiques ON contacts_specifiques.id_contact = contacts.id_contact
  7. INNER JOIN societes ON contacts.id_societe = societes.id_societe
  8. INNER JOIN societes_specifiques ON societes_specifiques.id_societe = societes.id_societe
  9. AND societes_specifiques.id_entite =2
  10. INNER JOIN script_etapes ON actions.etape = script_etapes.id_script_etape
  11. INNER JOIN societes_users ON societes_users.id_societe = societes.id_societe
  12. AND societes_users.id_campagne =1
  13. WHERE actions.enregistrement_ok =1
  14. AND actions.sommeil =0###############
  15. AND actions.id_contact
  16. IN (
  17. SELECT A3.id_contact
  18. FROM actions AS A3
  19. INNER JOIN script_etapes S1 ON A3.etape = S1.id_script_etape
  20. WHERE S1.groupe_etape =3
  21. AND A3.resultat =0
  22. HAVING 0 = (
  23. SELECT COUNT( * )
  24. FROM actions A4
  25. INNER JOIN script_etapes ON A4.etape = script_etapes.id_script_etape
  26. WHERE script_etapes.groupe_etape =3
  27. AND A4.id_contact = A3.id_contact
  28. AND A3.id_action <> A3.id_action )
  29. )
  30. AND actions.id_action = (
  31. SELECT MAX( id_action )
  32. FROM actions AS A2
  33. INNER JOIN script_etapes AS S3 ON A2.etape = S3.id_script_etape
  34. WHERE A2.id_contact = actions.id_contact
  35. AND S3.groupe_etape =1
  36. )


Message édité par PETOZAK le 09-09-2005 à 16:50:53
mood
Publicité
Posté le 09-09-2005 à 15:31:03  profilanswer
 

n°1196850
Arjuna
Aircraft Ident.: F-MBSD
Posté le 11-09-2005 à 02:04:38  profilanswer
 

Comme je dis toujours :
"Remplace ton IN par un EXISTS".
 
Le coup du "HAVING 0 = count (*) ..." je ne suis pas convaincu : le HAVING s'effectue lors du postprocessing, c'est à dire que c'est un filtre appliqué une fois la requête terminée, donc tu vas lire inutilement les lignes qui ne seront pas rammenée.
 
Sinon, là où tu pourras optimiser un maximum, c'est certainement sur les index : vérifie qu'ils sont "parfaits" pour ta requête (l'ensemble des champs des critères de filtre doivent participer à un index, pas un champ de moins ni de plus).
Et enfin, regarde si ton SGBD connait ce qu'on appelle les "query hints", qui te permettront de lui indiquer les meilleurs index en outrepassant les décisions de l'optimiseur.
 
Dans tous les cas, vérifie que tu n'as pas dans ton plan d'éxécution :
- RANGE SCAN
- TEMPORARY TABLE
- FULL SCAN (sauf si t'as un endroit où tu ne fais volontairement aucun filtre)

n°1196890
Beegee
Posté le 11-09-2005 à 10:43:08  profilanswer
 

Je ne serai pas aussi catégorique, un FULL SCAN peut souvent être plus rapide qu'un passage par un index (exemple : quand on récupère une grosse partie d'une table).
 
Maintenant, c'est clairement la partie dans ton IN qu'il faudrait réécrire / simplifier.
Suivant ton SGBD, ça peut valoir le coup de mettre des sous-requêtes dans le FROM directement et de faire des jointures dessus, plutôt que des IN / EXISTS.

n°1198068
PETOZAK
Posté le 13-09-2005 à 09:41:25  profilanswer
 

Salut,
Je voulais savoir si la requete à l'interieur de mon IN est executée àchaque fois ou bien une seule fois?
L'ensemble renvoyé étant statique et ne dépendant pas de la requete mère, ce serait trés dommage qu'elle soit executée à chaque fois , non?

n°1198070
betsamee
Asterisk Zeperyl
Posté le 13-09-2005 à 09:42:20  profilanswer
 

pourquoi alors ne pas les mettre dans le from?

n°1198081
PETOZAK
Posté le 13-09-2005 à 09:47:32  profilanswer
 

Arjuna a écrit :

Comme je dis toujours :
"Remplace ton IN par un EXISTS".)


 
----> Ce IN est il exexuter une fois ou plusieurs?
 

Arjuna a écrit :


Le coup du "HAVING 0 = count (*) ..." je ne suis pas convaincu : le HAVING s'effectue lors du postprocessing, c'est à dire que c'est un filtre appliqué une fois la requête terminée, donc tu vas lire inutilement les lignes qui ne seront pas rammenée.


---->,Postprocessing,effectivement, c'est d'ailleurs pour ca que je l'utilise afin d'eviter de le relancer à chaque fois, sion tu propposes quoi? une sous requete?
 

Arjuna a écrit :


Sinon, là où tu pourras optimiser un maximum, c'est certainement sur les index : vérifie qu'ils sont "parfaits" pour ta requête (l'ensemble des champs des critères de filtre doivent participer à un index, pas un champ de moins ni de plus).


---> Les Index tu les assigne pas uniquement pour les clés et les les jointures? :??:  
 

Arjuna a écrit :


Et enfin, regarde si ton SGBD connait ce qu'on appelle les "query hints", qui te permettront de lui indiquer les meilleurs index en outrepassant les décisions de l'optimiseur.


---->Pas sur que mysql le gere?
 

Arjuna a écrit :


Dans tous les cas, vérifie que tu n'as pas dans ton plan d'éxécution :
- RANGE SCAN
- TEMPORARY TABLE
- FULL SCAN (sauf si t'as un endroit où tu ne fais volontairement aucun filtre


---->je connais la commande sous oracle et SQLServer mais pas Mysql, c'est quoi?


Message édité par PETOZAK le 13-09-2005 à 09:48:25
n°1198101
PETOZAK
Posté le 13-09-2005 à 09:56:51  profilanswer
 

betsamee a écrit :

pourquoi alors ne pas les mettre dans le from?


C'est une excellent idée :)
J'y ai pensé au meme moment que toi :)...
J'espere que CA LE FERA

n°1198313
betsamee
Asterisk Zeperyl
Posté le 13-09-2005 à 11:25:46  profilanswer
 

perso pour un probleme quasi similaire ca l'a fait gravement pour moi

n°1198572
PETOZAK
Posté le 13-09-2005 à 15:17:07  profilanswer
 

Code :
  1. SELECT SQL_CALC_FOUND_ROWS
  2.        DATE_FORMAT(A.date_recontact, '%d/%m/%Y' ) AS date_recontact,
  3.        LE.resultat, C.id_contact, C.nom,
  4.        SS.topage, SS.score_societe,
  5.        S.id_societe,
  6.        SE.groupe_etape,
  7.        s_est_deplace, operation_a_effectuer,
  8.        SUBSTRING(A.heure_recontact, 1, 5 ) AS heure_recontact,
  9.        S.nom, A.id_action, A.id_contact, C.fonction_autre
  10. FROM   actions A
  11.        LEFT OUTER JOIN lignes_etape LE                  ON A.resultat = LE.id_ligne_etape
  12.        INNER JOIN script_etapes SE                      ON A.etape = SE.id_script_etape
  13.        INNER JOIN contacts C                            ON A.id_contact = C.id_contact
  14.              INNER JOIN contacts_specifiques CS         ON C.id_contact = CS.id_contact
  15.              INNER JOIN societes S                      ON C.id_societe = S.id_societe
  16.                    INNER JOIN societes_specifiques SS   ON S.id_societe = SS.id_societe
  17.                    INNER JOIN societes_users SU         ON S.id_societe = SU.id_societe
  18. WHERE  SU.id_campagne = 1
  19.   AND  SS.id_entite = 2
  20.   AND  A.enregistrement_ok = 1
  21.   AND  C.plus_dans_la_soc = 0
  22.   AND  A.sommeil = 0###############
  23.   AND A.id_contact IN (SELECT A3.id_contact
  24.                        FROM   actions AS A3
  25.                               INNER JOIN script_etapes S1 ON A3.etape = S1.id_script_etape
  26.                        WHERE  S1.groupe_etape = 3
  27.                          AND  A3.resultat = 0
  28.                          AND NOT EXISTS (SELECT 0
  29.                                          FROM   actions A4
  30.                                                 INNER JOIN script_etapes ON A4.etape = script_etapes.id_script_etape
  31.                                          WHERE  script_etapes.groupe_etape =3
  32.                                            AND  A4.id_contact = A3.id_contact
  33.                                            AND  A3.id_action <> A3.id_action)
  34.   AND actions.id_action = (SELECT MAX( id_action )
  35.                            FROM   actions AS A2
  36.                                   INNER JOIN script_etapes AS S3 ON A2.etape = S3.id_script_etape
  37.                            WHERE  A2.id_contact = actions.id_contact
  38.                              AND S3.groupe_etape =1)


 
 
Salut voila le resultat, j'ai divisé par 10 le temps d'execution  :love:  
merci à tous  :hello:

n°1198577
betsamee
Asterisk Zeperyl
Posté le 13-09-2005 à 15:19:13  profilanswer
 

pas la force d'analyser ton code , peux tu dire en gros comment tu t'y es pris , ca pourra toujours aider a l'occase
merci


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

  Aidez moi à optimiser cette requete plize!

 

Sujets relatifs
Requete HTTP[Résolu] Requête WHERE : ça coince
Requete commune a 2 db sqlAccès requête avec fonctions sous Access
Aidez un pauvre débutantAppeler une requête depuis le code
[SQL] requête qui semble simple mais j'ai du mal...Afficher le résultat d'une requête PHP et MySQL
Envoyer une requête post (côté serveur) via un objet asp ?Requête qui cherche plusieurs valeurs simultanément
Plus de sujets relatifs à : Aidez moi à optimiser cette requete plize!


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