Performance interface, requête sql trop longue, inutilisable.
Bonjour à tous,
maintenant que j'ai migré 2 années de données dans ma gpao "maison" je teste mes interfaces et je me rends compte que ça rame pas mal. Ca vient peut être de la façon dont j'ai construit mes fenêtres, qui comportent systématiquement des tables remplies par requêtage et filtrage via des listes.
L'exemple ici est l'interface d'interrogation des factures. J'ai migré plus de 4500 factures, et mon interface fait une pagination en n'affichant que 100 lignes à l'écran, et éventuellement on change de page.
Avant même l'affichage de cet écran, j'attends 20 secondes que ça charge (appli figée ne répond pas), ensuite ça se débloque et je vois ça :
http://img4.hostingpics.net/pics/150556interrofc.jpg
J'ai testé avec l'analyseur de performances :
http://img4.hostingpics.net/pics/798212perfs.jpg
Et ce sont bien les 2 appels à HExécuteRequêteSQL qui consomment les 99,9% du temps de chargeFactures (voir code plus bas).
Pourtant ma requête est sensée me ramener seulement 100 lignes, ce qui n'est quand même pas le bout du monde. Alors je m'interroge sur le pourquoi de cette lenteur. Je me permets de coller le code la procédure chargeFactures, qui s'exécute chaque fois que je tape dans un champs ou que je sélectionne dans une liste.... J'ai essayé de la threader mais c'est encore plus long (affichage progressif mais très lent) !
Code:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| PROCEDURE chargeFactures(LOCAL page_selectionnee est un entier = 1)
nb_requetes ++
// ça c'est pour ne pas exécuter la procédure inutilement à l'initialisation de l'interface
// car elle est déclenchée sur sélection d'un élément de chacune des listes Client, Commande ou Article
// ici, ignore_n_premieres_requetes vaut 3
SI nb_requetes <= ignore_n_premieres_requetes ALORS RETOUR
TableSupprimeTout(TABLE_Factures)
criteres est une chaîne = ""
criteres2 est une chaîne = ""
img est une chaîne = ""
SI LISTE_Commandes > 0 ALORS
criteres = " WHERE cc_id = " + LISTE_Commandes
SINON
SI SAI_filtre1 <> "" ALORS
criteres = " WHERE cc_num LIKE '%" + Replace(SAI_filtre1, "*", "%") + "%'"
SINON
// critere pour obligatoirement avoit un WHERE
criteres = " WHERE fcl_id > 0"
FIN
FIN
SI LISTE_Articles > 0 ALORS
criteres = criteres + " AND art_id = " + LISTE_Articles
SINON
SI SAI_filtre2 <> "" ALORS
criteres = criteres + " AND (art_reference LIKE '%" + Replace(SAI_filtre2, "*", "%") + "%' OR (fcl_article_id = 0 AND fcl_commentaire LIKE '%" + Replace(SAI_filtre2, "*", "%") + "%'))"
FIN
FIN
SI LISTE_Clients > 0 ALORS
criteres2 = "AND clt_id = " + LISTE_Clients
SINON
criteres2 = "AND clt_code LIKE '%" + Replace(SAI_filtre, "*", "%") + "%'"
FIN
// PREMIERE REQUETE POUR CONNAITRE LE NOMBRE DE PAGES
Sql est une chaîne = "SELECT count(fc_id) AS nblignes FROM fc,clt, dev " +
"WHERE fc_id IN (SELECT DISTINCT fcl_fc_id FROM " +
"(((fcl FULL OUTER JOIN cc ON fcl_bl_cc_id = cc_id) " +
"FULL OUTER JOIN ccl ON fcl_bl_ccl = ccl_ligne) " +
"FULL OUTER JOIN art ON fcl_article_id = art_id) " +
criteres + ") AND fc_client = clt_id AND fc_devise = dev_id " + criteres2
Rs est une Source de Données
nblignes est un entier = 0
nbpages est un entier = 1
SI PAS HExécuteRequêteSQL(Rs,Cnx,hRequêteSansCorrection,Sql) ALORS
Erreur("Erreur d'initialisation de la requête"+RC+HErreurInfo()+ RC + RC + Sql)
RETOUR
FIN
SI HLitPremier(Rs) ALORS
nblignes = Rs.nblignes
FIN
HLibèreRequête(Rs)
//info(nblignes)
critere_pagination est une chaîne = ""
SI COMBO_nb_lignes..ValeurAffichée <> "TOUT" ALORS
premiere_ligne est un entier = ((page_selectionnee - 1) * Val(COMBO_nb_lignes..ValeurAffichée) + 1)
derniere_ligne est un entier = premiere_ligne + Val(COMBO_nb_lignes..ValeurAffichée) - 1
critere_pagination = "WHERE a.ligne >= " + premiere_ligne + " AND a.ligne <= " + derniere_ligne
nbpages = PartieEntière(nblignes / Val(COMBO_nb_lignes..ValeurAffichée))
SI PartieDécimale(nblignes / Val(COMBO_nb_lignes..ValeurAffichée)) > 0 ALORS
nbpages ++
FIN
SI nbpages = 0 ALORS nbpages = 1
FIN
LIB_nbpages = "/ " + nbpages
ListeSupprimeTout(COMBO_page)
POUR i = 1 _A_ nbpages
ListeAjoute(COMBO_page,i)
FIN
ListeSelectPlus(COMBO_page,page_selectionnee)
Sql = "SELECT* FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY fc_id Desc) AS ligne FROM fc,clt, dev " +
"WHERE fc_id IN (SELECT DISTINCT fcl_fc_id FROM " +
"(((fcl FULL OUTER JOIN cc ON fcl_bl_cc_id = cc_id) " +
"FULL OUTER JOIN ccl ON fcl_bl_ccl = ccl_ligne) " +
"FULL OUTER JOIN art ON fcl_article_id = art_id) " +
criteres + ") "+
"AND fc_client = clt_id AND fc_devise = dev_id " + criteres2 + ") a " + critere_pagination
//trace(Sql)
SI PAS HExécuteRequêteSQL(Rs,Cnx,hRequêteSansCorrection,Sql) ALORS
Erreur("Erreur d'initialisation de la requête"+RC+HErreurInfo()+ RC + RC + Sql)
RETOUR
FIN
SI HLitPremier(Rs) ALORS
TANTQUE PAS HEnDehors(Rs)
img = "delete.png"
TableAjoute(TABLE_Factures, Rs.fc_id + TAB + Rs.fc_num + TAB + Rs.clt_code + TAB + Rs.fc_total_ht + TAB + Rs.fc_taux_tva + TAB + Rs.fc_total_tva + TAB + Rs.fc_total_ttc + TAB + Rs.fc_emballage + TAB + Rs.fc_port + TAB + Rs.fc_assurance + TAB + Rs.fc_total_facture + TAB + Rs.dev_nom + TAB + Rs.fc_date + TAB + img)
HLitSuivant(Rs)
FIN
FIN
HLibèreRequête(Rs)
SI TABLE_Factures..Vide ALORS
BTN_IMPRIMER..Grisé = Vrai
SINON
BTN_IMPRIMER..Grisé = Faux
FIN |
Ensuite quand j'essaye d'interagir avec l'interface, par exemple commencer à saisir un nom de client, ça prend entre 5 et 10 secondes à chaque caractère tapé, avant de retrouver la main dans le champs de saisie...
Bref, c'est pas possible de faire bosser les gens comme ça.
Il faut que je trouve une solution rapidement, j'aimerais déployer mon appli fin Janvier.
Toute aide est la bienvenue, merci d'avance.
EDIT : ça semble venir de la construction de ma requête Sql (la deuxième, la plus complexe à mon avis) car à titre de comparaison j'ai un écran d'interrogation des livraisons, qui me ramène encore d'avantage de lignes (125 pages de 100 lignes) et l'écran se charge initialement en moins de 3 secondes et se réactualise assez bien à chaque saisie...