Optimiser une requête pour diminuer le temps d'execution

Signaler
-
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
-
Bonjour à tous,
J'ai une requête alimentant un état assez longue.

Quelqu'un aurait-il une idée pour la raccourcir un peu ...


Query2.Close;
Query2.SQL.Clear;
Query2.SQL.ADD('Select DetplanningInteg.compteur as cpt,SaiPers.Nom as Nom,SaiPers.Prenom as Prenom,DetplanningInteg.Debutthem as Debut,DetplanningInteg.Finthem as fin, ThemInteg.Libelle,DetplanningInteg.Validation_a_chaud as ValC,
'DetplanningInteg.Validation_a_Froid as ValF,DetplanningInteg.Date_evaluation_chaud as DateEvalC,DetplanningInteg.Date_evaluation_froid as DateEvalF From DetPlanningInteg , SaiPers, ThemInteg where DetplanningInteg.Matricule = SaiPers.Matricule and '+quotedStr(dateP)+'= DetplanningInteg.debutthem and libelle in ( select libelle from themInteg where DetplanningInteg.ThemCode = themInteg.Code)'+
or DetplanningInteg.Matricule SaiPers.Matricule and '+quotedStr(dateP)+' < DetplanningInteg.finthem and'+quotedStr(dateP)+' > DetplanningInteg.Debutthem and libelle in ( select libelle from themInteg where DetplanningInteg.ThemCode themInteg.Code)order by Nom');
Query2.open;




Merciiiiiiiiiiiiiiiii

21 réponses

Messages postés
675
Date d'inscription
jeudi 17 avril 2008
Statut
Membre
Dernière intervention
19 février 2019
13
Salut
Est-ce si important que cela que se soit plus court ?
Si ça marche comme cela, autant le laisser sans trafiquer
Maintenant si ça marche pas, c'est autre chose !


Dubois77
site perso
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
Si ça marche comme cela, autant le laisser sans trafiquer

Je suis pas tout a fait d'accord avec toi Dubois, pourquoi attendre quelque chose que tu pourrai avoir sans attendre. Personnellement, je trouve qu'un logiciel ou tu passe ton temps a attendre qu'il réagisse est assez rebutant.

Donc, pour en revenir au problème (ou plutôt à l'optimisation ;) ), je crois que le ralentissement vient de ton select imbriqué qui force une sous requête pour chaque ligne. N'est il pas possible de l'inclure dans ta condition ?
Est-ce que quelque-chose comme ca te donne les même résultats ?
(...) WHERE 
  (DetplanningInteg.Matricule = SaiPers.Matricule) AND
  (DetplanningInteg.ThemCode = themInteg.Code) AND
  ('dateP' < DetplanningInteg.finthem) AND
  ('dateP' >= DetplanningInteg.Debutthem) 
ORDER BY (...)
(j'ai volontairement mis le dateP en clair, sans me soucier du formatage que je te laisse replacer)
Messages postés
420
Date d'inscription
samedi 17 mai 2003
Statut
Membre
Dernière intervention
6 mai 2019
16
Salut,

C'est la question qui est ambiguë.
Qu'est-ce qui est trop long :
- le code ?
- le temps d'exécution ?
salut,
Korgis: le temps d'exécution qui est long je cherche à l'optimiser.
Guillemouze : merciiii bcp pour ton aide :)
Korgis: pour ta proposition j 'ai déjà essayé cette requête, et le résultat ne correspond pas à ce que je cherche :(
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Salut,

Je ne sais pas si tu auras exactement le même résultat avec la requête ci dessous (peut être qu'il te faudra changer le type de jointure et essayer de l'adapter, c'est un début de piste...)
Pense à utiliser des alias de tables, ça améliore la lisibilité. Je ne vois pas bien non plus l'utilité du renommage des champs (ça doit consommer un peu de CPU pour pas grand chose...)
La clause "Where" que tu demandes m'a l'air un peu incohérente (Le "And" est prioritaire sur le "Or"...). Tu demandes "'+quotedStr(dateP)+'= DetplanningInteg.debutthem" et "+quotedStr(dateP)+' > DetplanningInteg.Debutthem"

Select t1.compteur as cpt, t2.Nom as Nom, t2.Prenom as Prenom, t1.Debutthem as Debut,
t1.Finthem as fin, t3.Libelle, t1.Validation_a_chaud as ValC, t1.Validation_a_Froid as ValF,
t1.Date_evaluation_chaud as DateEvalC, t1.Date_evaluation_froid as DateEvalF
From DetPlanningInteg t1
INNER JOIN SaiPers t2 ON t1.Matricule = t2.Matricule
INNER JOIN ThemInteg t3 ON t1.ThemCode = t3.Code
where
'+quotedStr(dateP)+'= t1.debutthem
and '+quotedStr(dateP)+' < t1.finthem
and'+quotedStr(dateP)+' > t1.Debutthem
order by Nom


Simon
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
[quote=simon]
'+quotedStr(dateP)+'= t1.debutthem (...)
and'+quotedStr(dateP)+' > t1.Debutthem/quote
heuuuu j'ai bien peur que ce soit toujours false
'+quotedStr(dateP)+'>= t1.debutthem
serait mieux ;)

Et je pense que le resultat de ta requete serait le meme que le mien. J'ai l'impression que ce n'est pas une jointure 1-1 sur le ThemCode.

Peut etre qu'un SELECT DISTINCT (...) donnerait le bon resultat, mais impossible à savoir sans connaitre les relations entre les tables
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Attention, le "Distinct" ça consomme ! A n'utiliser vraiment que si nécessaire...

@Guillemouze :
heuuuu j'ai bien peur que ce soit toujours false
'+quotedStr(dateP)+'>= t1.debutthem
serait mieux ;)


-> on est bien d'accord... C'est pour ça que je l'ai mis en rouge

@dakhlifaten :
Si tu peux nous expliquer de manière littérale comment sont construites tes tables (description des champs) et ce que tu veux récupérer (qu'est ce que le DateP ? une valeur ?), on pourra t'aider un peu plus...


Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
@Guillemouze:
J'ai l'impression que ce n'est pas une jointure 1-1 sur le ThemCode.

Effectivement, ce n'est pas évident... A mon avis il manque quelques parenthèses dans la clause "where" pour ordonner les priorités And/Or...

Simon
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
Le renommage des champs, je penses que c'est pour publiposter sur son etat, et je suis pas sur que ce soit tres consommateur.
En ce qui concerne le distinct, je suis pas sur, mais je crois que c'est moins consommateur qu'un WHERE truc IN (SELECT ...)
Quant à dateP, j'ose supposer qu'il s'agit d'une date, et qu'il verifie qu'elle est bien comprise entre le début (inclus) et la fin (exclue) de je ne sais quoi.
Un simple reformattage du WHERE donnerait ceci (avec le meme resultat assuré que sa requete actuelle) :
where DetplanningInteg.Matricule = SaiPers.Matricule and'
+quotedStr(dateP)+' < DetplanningInteg.finthem and'
+quotedStr(dateP)+' >= DetplanningInteg.Debutthem and 
libelle in ( select libelle from themInteg where DetplanningInteg.ThemCode = themInteg.Code)
order by Nom

Mais ATTENTION, je crois que ta requete à la base n'est pas bonne car tu as la table ThemInteg dans les FROM mais tu n'as pas de jointure, donc je crois que tu aura le nombre de resultats escompté * le nombre d'enregistrements dans la table ThemInteg
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Beuh ! et ça c'est pas une jointure sur ThemInteg ?

INNER JOIN ThemInteg t3 ON t1.ThemCode = t3.Code

Par contre, je ne suis effectivement pas sûr de mon résultat, mais je ne sais pas non plus si notre ami récupère bien les enregistrements auxquels il s'attend... Partant de là...
D'une manière générale, j'ai plutôt tendance à utiliser les jointures plutôt que les sous requetes (à chaque fois que c'est possible) ou les where Table1.champ1 = Table2.champ2 (que j'ai définitivement proscrits). J'avais constaté, mais ce n'est pas systématique, que mes requêtes étaient plus performantes avec des jointures que des sous requêtes...

Simon
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
[quote=simon]Beuh ! et ça c'est pas une jointure sur ThemInteg ?/quote
Je parlais de la requête de Dakhlifaten . Du coup ta requête n'a pas le même comportement (même si je suppose que le tien ressemble plus au comportement qu'il serait logique d'avoir).
Bref, je suis prêt à mettre ma main à couper au feu que sa requête ne donne pas les résultats attendus à la base.
En ce qui concerne les sous requêtes, comme je l'ai dit précédemment, c'est on ne peut plus consommateur, étant donné que pour chaque ligne de la requête principale, le SGBD va relancer une requête (1000 lignes -> 1001 requêtes au total, sauf si le SGBD met en cache les sous requêtes sur des paramètres identiques). Mais on ne peut pas toujours remplacer une sous-requête par une jointure, et je dirais même que les quelques cas où c'est possible, c'est que la sous-requête n'aurait jamais dû être là !
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Alors, en relisant, en interprétant un peu et en ajoutant des parenthèses, j'ai l'impression que notre ami voudrait faire un truc comme ça :

where (DetplanningInteg.Matricule = SaiPers.Matricule
and '+quotedStr(dateP)+'= DetplanningInteg.debutthem
and libelle in (select libelle from themInteg where DetplanningInteg.ThemCode = themInteg.Code))
or (DetplanningInteg.Matricule = SaiPers.Matricule
and '+quotedStr(dateP)+' < DetplanningInteg.finthem
and'+quotedStr(dateP)+' > DetplanningInteg.Debutthem
and libelle in ( select libelle from themInteg where DetplanningInteg.ThemCode = themInteg.Code))
order by Nom

qui pourrait être factorisé de la sorte :
where DetplanningInteg.Matricule = SaiPers.Matricule
and libelle in (select libelle from themInteg where DetplanningInteg.ThemCode = themInteg.Code))
and
(('+quotedStr(dateP)+'= DetplanningInteg.debutthem)
or
('+quotedStr(dateP)+' < DetplanningInteg.finthem
and'+quotedStr(dateP)+' > DetplanningInteg.Debutthem))

Du coup, on peut transformer le "DetplanningInteg.Matricule SaiPers.Matricule" en jointure et je serai tenté de passer aussi "libelle in (select libelle from themInteg where DetplanningInteg.ThemCode themInteg.Code))" en jointure sur "DetplanningInteg.ThemCode = themInteg.Code".

Non ?


Simon
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
[quote=simon]qui pourrait être factorisé de la sorte (...)/quote
et sachant que [(x=a) ou ((x > a) et (x < b))] <=> [(x >= a) et (x < b)]
sauf dans le cas ou b < a, ce qui est a priori peu plausible, sinon debutThem < finThem, ce qui est louche. On en revient a ce que j'ai proposé tout a l'heure


[quote=simon]je serai tenté de passer aussi "libelle in (select libelle from themInteg where DetplanningInteg.ThemCode = themInteg.Code))" en jointure sur "DetplanningInteg.ThemCode = themInteg.Code"./quote
c'est ce que j'avais proposé aussi dans ma première réponse (dans un WHERE et non pas un JOIN, mais le resultat est le meme), mais :
[quote=dakhlifaten]j 'ai déjà essayé cette requête, et le résultat ne correspond pas à ce que je cherche/quote ... mais il n'est pas précisé que c'est a cause de la jointure que le résultat n'est pas le bon.
Donc en attendant d'avoir plus d'informations de l'auteur, je trouve qu'on a déjà émis pas mal de suppositions
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
oulala !!!

et sachant que [(x=a) ou ((x > a) et (x < b))] <=> [(x >= a) et (x < b)]


Là tu écartes de la requête les enregistrements pour lesquels finThem est égal (ou inférieur mais j'avoue, c'est peu cohérent) à debutThem ou nul. Ce n'est pas du tout équivalent...
D'une part :
- x est égal à a (et peu importe la valeur de b)
ou
- x est compris entre a et b (bornes non incluses)
D'autre part :
- x est compris entre a (borne incluse) et b (borne non incluse)

Si dans DetplanningInteg il y a des événements sur un seul jour (debutthem et finthem à la même valeur) ou pour lesquels il n'y a pas encore de fin prévue (debutthem valorisée et finthem à null), ce qui sur un planning est tout à fait concevable, ils ne passeront pas dans ton équivalence.

Je suis chiant, hein ?

Simon
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
[quote=simon]Je suis chiant, hein ?/quote
Pas du tout, la réctification est de rigeur
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Bon, je suis rassuré...
Mais que fait l'auteur ???? C'est pas tout de nous mettre l'eau à la bouche...

Simon
Messages postés
2106
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
Ne sous-estimez pas non plus la création d' un index sur le bon champ qui peut diviser par 10 le temps d' exécution!

a+


Composants Cindy pour Delphi
Faites une donation.
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Certes, Mauricio, certes ! On attend (impatiemment) la description de la bdd...

Simon
Messages postés
2106
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
... et le nombre d' enregistrements de chaque table!


Composants Cindy pour Delphi
Faites une donation.