Page 1 sur 2
Problème de requête trop lourde
Posté : 08 nov. 2005, 14:28
par SwiTz
Voila je suis un habitué des questions qui sont un peu bizarre, mais je sais pas comment faire cela. J'ai une table contenant (attention accrochez vous ) plus de 1.000.000 de lignes de donnés.
Et je dois faire des requêtes dessus afin d'extraire les donnnées et les mettre en forme pour les utilisateur. Le problème c'est que le temps d'éxécution d'une de ces requêtes est d'environ 1m30 voir 2min.
Le hic c'est que pour l'utilisateur quand il doit voir ses données, le temps d'attente dois être infime. Je voudrais savoir si il y aurai une méthode de conception qui me permettrai d'avoir un temps d'éxécution pour l'utilisateur qui soit très petit.
Voiçi une de mes requêtes sql :
Code : Tout sélectionner
select sum(ca_gecaprod.CA_MOIS) as CA_CUM_M, ddv.NOM_DDV, ca_gecaprod.DOM_VENTE, ca_gecaprod.ANNEE
from ca_gecaprod,client,vendeur,rdv,ddv
where ca_gecaprod.ID_CLT = client.ID_CLT and client.VL = vendeur.NOM_VENDEUR and vendeur.ID_RDV = rdv.ID_RDV and rdv.ID_DDV = ddv.ID_DDV and ca_gecaprod.ID_MOIS<5
GROUP BY ca_gecaprod.DOM_VENTE, ddv.NOM_DDV, ca_gecaprod.ANNEE
having ca_gecaprod.ANNEE = 2004;
Posté : 08 nov. 2005, 14:32
par rami
J'aurais plutôt écrit ce message dans le forum Base de données.
Tu as des index sur les champs utilisés pour les jointures?
Tu es sous quelle base de données?
Posté : 08 nov. 2005, 14:42
par zeus
Modération : Sujet déplacé
Sinon, est-ce que tu as pensé à utiliser des index sur les champs de tri pour augmenter la vitesse de traitements?
Posté : 08 nov. 2005, 14:58
par SwiTz
Ma base de donnée tourne sous mysql, et pour les index je ne jamais encore vu ça il faudrai que je lise des articles dessus, car j'en entends pas mal parler
Posté : 08 nov. 2005, 15:10
par rami
Il faut que tu crées des index sur les champs utilisés pour les jointures (les clé étrangères en gros), et les champs sur lesquels tu utilises des critères de sélection.
http://dev.mysql.com/doc/refman/5.0/fr/indexes.html
Posté : 08 nov. 2005, 15:52
par SwiTz
Oui on pensai également avec mon maitre d'apprentissage à faire les 3 requêtes puis fusionner leur résultats dans une table finale qui serai stocké dans la BD.
Mais alors je voudrais savoir si il est possible de stocker temporairement le resultat d'une requête et de l'utiliser plus tard dans une autre requête comme une requête de jointure par exemple ?
Posté : 08 nov. 2005, 16:04
par Cyrano
Ça peut très bien se faire en une seule requête, d'autant que celle-ci n'est pas complexe. Un détail pourtant :
Code : Tout sélectionner
SELECT sum(ca_gecaprod.CA_MOIS) AS CA_CUM_M, ddv.NOM_DDV, ca_gecaprod.DOM_VENTE, ca_gecaprod.ANNEE
FROM ca_gecaprod,client,vendeur,rdv,ddv
WHERE ca_gecaprod.ID_CLT = client.ID_CLT
AND client.VL = vendeur.NOM_VENDEUR
AND vendeur.ID_RDV = rdv.ID_RDV
AND rdv.ID_DDV = ddv.ID_DDV
AND ca_gecaprod.ID_MOIS < 5
GROUP BY ca_gecaprod.DOM_VENTE, ddv.NOM_DDV, ca_gecaprod.ANNEE
HAVING ca_gecaprod.ANNEE = 2004;
Pourquoi un HAVING au lieu de :
Code : Tout sélectionner
SELECT sum(ca_gecaprod.CA_MOIS) AS CA_CUM_M, ddv.NOM_DDV, ca_gecaprod.DOM_VENTE, ca_gecaprod.ANNEE
FROM ca_gecaprod,client,vendeur,rdv,ddv
WHERE ca_gecaprod.ID_CLT = client.ID_CLT
AND client.VL = vendeur.NOM_VENDEUR
AND vendeur.ID_RDV = rdv.ID_RDV
AND rdv.ID_DDV = ddv.ID_DDV
AND ca_gecaprod.ID_MOIS < 5
AND ca_gecaprod.ANNEE = 2004
GROUP BY ca_gecaprod.DOM_VENTE, ddv.NOM_DDV, ca_gecaprod.ANNEE;
Ensuite, comme ça t'a été dit, en indexant certaine colonnes, tu vas accélérer très notablement l'exécution des requêtes : tu dois indexer toutes les clé étrangères et les champs qui sont régulièrement sollicités.
Posté : 08 nov. 2005, 16:18
par SwiTz
Oui c'est vrai que le HAVING içi n'est pas necessaire mais comment je pourrai faire pour construire qu'une seule requête, dois je passer par des stockages dans des tables temporaire ?
Posté : 08 nov. 2005, 16:25
par Cyrano
Ta requête telle quelle est très bien: indexe tes champs et refais un test, tu verras bien.
Ou alors j'ai loupé un chapitre quelque part...

Posté : 08 nov. 2005, 16:37
par SwiTz
Ta requête telle quelle est très bien: indexe tes champs et refais un test, tu verras bien.
Ou alors j'ai loupé un chapitre quelque part...

Ah désolé cyrano, j'ai oublié de dire que j'ai des requêtes du même type mais avec des conditions différentes
Les voiçi donc :
Code : Tout sélectionner
select ddv.NOM_DDV, ca_gecaprod.DOM_VENTE, sum(ca_gecaprod.CA_MOIS) as CA_CUM_N1
from ca_gecaprod,client,vendeur,rdv,ddv
where ca_gecaprod.ID_CLT = client.ID_CLT and client.VL = vendeur.NOM_VENDEUR and vendeur.ID_RDV = rdv.ID_RDV and rdv.ID_DDV = ddv.ID_DDV and ca_gecaprod.ANNEE = 2004
group by ddv.ID_DDV, ca_gecaprod.DOM_VENTE;
select ddv.NOM_DDV, ca_gecaprod.DOM_VENTE, sum(ca_gecaprod.CA_MOIS) as CA_CUM_N1
from ca_gecaprod,client,vendeur,rdv,ddv
where ca_gecaprod.ID_CLT = client.ID_CLT and client.VL = vendeur.NOM_VENDEUR and vendeur.ID_RDV = rdv.ID_RDV and rdv.ID_DDV = ddv.ID_DDV and ca_gecaprod.ANNEE = 2005
group by ddv.ID_DDV, ca_gecaprod.DOM_VENTE;
select ddv.NOM_DDV, ca_gecaprod.DOM_VENTE, sum(ca_gecaprod.CA_MOIS) as CA_CUM_N1
from ca_gecaprod,client,vendeur,rdv,ddv
where ca_gecaprod.ID_CLT = client.ID_CLT and client.VL = vendeur.NOM_VENDEUR and vendeur.ID_RDV = rdv.ID_RDV and rdv.ID_DDV = ddv.ID_DDV and ca_gecaprod.ID_MOIS <= $mois and ca_gecaprod.ANNEE = 2004
group by ddv.ID_DDV, ca_gecaprod.DOM_VENTE;
Voila mon souhait ou mon voeux dans ce cas là serai d'avoir une requête qui fais les trois en même temps. Sinon de savoir si on peut stocker résultats des 3 requêtes dans des tableaux puis les fusionner pour avoir le tableau final
Posté : 08 nov. 2005, 16:50
par rami
Essaies dèjà de mettre des index. Après, si le temps de réponse ne convient toujours pas, tu pourras envisager une autre alternative plus "exotique".
Posté : 08 nov. 2005, 17:23
par Cyrano
La première chose que je remarque, c'est qu'à un détail près, les requêtes sont strictement les mêmes: la différence est la période recherchée :
- 2004
- 2005
- 2004 et mois <= à une variable $mois
Je ne sais pas comment fonctionne ton application, mais tu as deux solutions :
- faire trois requêtes pour obtenir trois gammes de résultats
- Faire une seule requête et trier ensuite par programmation pour avoir telle ou telle tranche.
La question qui se pose donc: comment vas-tu demander telle ou telle tranche ? Est-ce que ton formulaire a trois boutons et tu cliques sur l'un ou l'autre pour déclencher telle ou telle requête ?
En bref, il manque des morceaux pour te donner une réponse efficace.
Posté : 08 nov. 2005, 17:23
par SwiTz
Mon application à pour but de diffuser le chiffre d'affaires des directions des ventes. Les requêtes que j'ai donné concerne les données qu'un utilisateur qui est un directeur général veut voir, il voudrais un tableau de la forme suivante :
NOM_DDV DOM_VENTE CA_CUM_N-1 CA_CUM_N CA_AN_N-1
--------------------------------------------------------------------------------
Le CA_CUM_N-1 correspond au chiffre d'affaire cumulé de janvier N-1 (2004) jusqu'au mois $mois de l'année N-1
Le CA_CUM_N correspond au chiffre d'affaire cumulé de janvier N (2005) jusqu'au mois $mois de l'année N. Etant donné que la mise à jour ce fais mois par mois cela revient au calcul de tout les CA_MOIS de l'année 2005
Le CA_AN_N-1 correspond au chiffre d'affaires de l'année N-1 (2004)
Voila donc en gros ce que l'utilisateur souhaite avoir comme info
Posté : 08 nov. 2005, 17:31
par Cyrano
Fais une exportation de la structure (surtout pas les données, ça va planter phpMyAdmin) de ces tables dans phpMyAdmin et colle-ça ici qu'on voit un peu tes index, j'ai un doute. Si tes tables en des tables MyISAM, c'est très rapide à la base, si tes champs sont correctement indexés en plus, ça ne devrait pas poser de problème même avec 1 million d'enregistrements...

Posté : 08 nov. 2005, 17:34
par SwiTz
Je n'utilise pas PhPMyAdmin car là où je travaille il me font travailler sous Eclipse avec un module PHP/MySQL et MySQL est gérer par Eclipse :s