Problème de requête trop lourde

Eléphant du PHP | 88 Messages

08 nov. 2005, 14:28

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;
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"

Mammouth du PHP | 983 Messages

08 nov. 2005, 14:32

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?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

08 nov. 2005, 14:42

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?
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Eléphant du PHP | 88 Messages

08 nov. 2005, 14:58

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
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"

Mammouth du PHP | 983 Messages

08 nov. 2005, 15:10

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

Eléphant du PHP | 88 Messages

08 nov. 2005, 15:52

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 ?
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"

Mammouth du PHP | 19672 Messages

08 nov. 2005, 16:04

Ç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.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 88 Messages

08 nov. 2005, 16:18

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 ?
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"

Mammouth du PHP | 19672 Messages

08 nov. 2005, 16:25

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...:-k
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 88 Messages

08 nov. 2005, 16:37

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...:-k
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 :D

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
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"

Mammouth du PHP | 983 Messages

08 nov. 2005, 16:50

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".

Mammouth du PHP | 19672 Messages

08 nov. 2005, 17:23

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.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 88 Messages

08 nov. 2005, 17:23

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
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"

Mammouth du PHP | 19672 Messages

08 nov. 2005, 17:31

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... :-k
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 88 Messages

08 nov. 2005, 17:34

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
PHP Lover "Plus je découvre PHP, plus je l'aime. Lui et moi c'est pour la vie !"