Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > PHP & MySQL
PHP & MySQL Forum d'entraide sur les fonctions MySQL avec PHP. Avant de poster -> FAQ MySQL, Cours MySQL et Sources MySQL. Pour les questions concernant le moteur MySQL plutôt que les fonctions PHP, merci d'utiliser le forum MySQL.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 18/02/2011, 11h42   #1
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
Par défaut Optimisation d'une requête

Bonjour à tous,

J'ai 3 tables (je simplifie et schématise):

- produits :
champs : id, reference, nom, prix
clé primaire sur id

- catégories :
champs : id, nom
clé primaire sur id

- produits_categories :
champs : produit_id, categorie_id
clés sur produit_id et categorie_id

Pour afficher une liste de produits avec le nom de leur catégorie, je fais la requête suivante :

Code :
1
2
3
4
 
SELECT p.id, p.reference, p.nom, p.prix, c.nom AS categorie
FROM produits p LEFT OUTER JOIN produits_categories pc ON p.id = pc.produit_id
LEFT OUTER JOIN categories c ON c.id = pc.categorie_id
Mais avec 800 produits, ça rame un peu...
Une idée pour améliorer cette requête ?
Merci d'avance.
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 11h50   #2
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
800 entrées c'est petit.
Combien de temps mets ta requête a s'exécuter ?
sabotage est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 12h12   #3
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
Bonjour,

Près de 20 secondes...
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 12h19   #4
Membre éclairé
 
Homme Jérémy
Étudiant
Inscription : octobre 2009
Messages : 236
Détails du profil
Informations personnelles :
Nom : Homme Jérémy
Localisation : France

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Produits et services télécom et Internet

Informations forums :
Inscription : octobre 2009
Messages : 236
Points : 322
Points : 322
A mon avis, ton problème ne vient à mon avis pas de ta requête, il y a eu un topic sur un peu le même soucis, ta connexion à ta base se fait par 'localhost' ou '127.0.0.1' ?

Dans certains cas (allez savoir pourquoi) localhost peine à se connecter.
gwharl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 12h37   #5
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
Bonjour,

Non sur un serveur web 1 and 1...
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 13h11   #6
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Est ce que tu as le même problème en local ? Si tel est le cas tu peux savoir où ça coince avec xdebug en activant le profiling (utilise webgrind pour parser les fichiers de profiling).

Juste une question: pourquoi utilises-tu les outer join là ou des join simples suffiraient.
Personnellement, je n'ai jamais rencontré de problèmes en utilisant cette forme:
Code :
1
2
3
4
5
 
SELECT A.id, B.name
FROM `tableA` as A
JOIN `tableB` as B 
ON (A.id=B.tableA_id);
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 13h17   #7
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
Tu peux utiliser une requête EXPLAIN pour voir.
sabotage est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 14h11   #8
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
A Benjamin Delespierre :

Déjà, en utilisant JOIN au lieu de OUTER JOIN je gagne un temps considérable.
Merci à toi.

A Sabotage : je ne connais pas explain, je vais regarder la doc.
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 19h22   #9
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
J'ai encore besoin de vos lumières...
Si je reprends ma requête :

Code :
1
2
3
4
 
SELECT p.id, p.nom, c.nom AS categorie
FROM produits p JOIN produits_categories pc ON p.id = pc.produit_id
JOIN categories c ON c.id = pc.categorie_id
Elle fonctionne bien. Mais j'ai un petit souci, dans le cas où un produit est attaché à plusieurs catégories, il apparaît autant de fois dans la liste :

Table produits
id | nom |
1 | vélo |
2 | scooter |
3 | voiture |
4 | trottinette

Table catégories
id | nom
1 | véhicules
2 | jouet

table produits_categories
produit_id | categories_id
1 | 1
2 | 1
3 | 1
4 | 1
4 | 2

Dans ce cas, le produit "trottinette" s'affichera 2 fois. Comment faire en sorte qu'il ne s'affiche qu'une fois et que la ligne catégorie affiche la première des deux ?
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 22h56   #10
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Mets une clause distinct.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2011, 06h43   #11
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
Bonjour,

Déjà essayé : sans succès.
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2011, 07h28   #12
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Salut

Citation:
Près de 20 secondes...
Comment as tu obtenu ce temps ?
Est-ce vraiment uniquement cette requête qui met 20s ou c'est l'affichage de la page qui entre autre exécute la requête ?

Puis depuis combien de temps as tu remarqué cette lenteur ?
N'y a t-il pas eu des modifs effectuées qui pourrait laisser croire que ???

Aussi, tu n'as pas répondu à la question si tu remarquais le même problème en local, c'est pourtant important, ça peu donner une piste.

Il serait bon d'exporter ta Bdd, l'importer chez toi dans PhpMyAdmin (par exemple).
Ca fera déjà une sauvegarde, puis lancer la même requête, et voir ce que ça donne.

Aussi, as tu regarder (PhpMyAdmin toujours) si cette contient des pertes (les autres table par la même occasion).
N'y t-il pas d'autres tables qui semblerait anormal ?
PhpMyAdmin propose de faire certaine manip. sur les tables, comme optimisation, réparation, etc ..., et bien bien exécute les (Backup avant, cela va sans dire ).


Tu pourrais aussi, ne serait-ce vite fait, mettre des repères de temps (fonction microtime), au moins entre l'exécution de la requête.
Si ce n'est pas juste la requête qui cause problème, rajouter des repères à des phases clés dans ton code pourrait déceler certaines parties louches/douteuses.

De même, as tu exploiter un outil genre FireDebug qui fourni des temps de chargement de tous les élément que compose la page Web.
Même si c'est que coté client, on obtient les temps de réponse du serveur.


Optimiser les tables, le SQL, les index, etc ... sera en toute évidence un bénéfice.
Mais 20s c'est long, et il y a forcément un problème, où du moins une explication, donc même en optimisant, le problème restera entier.
Essai au moins de localiser au mieux où se situe la lenteur.
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2011, 09h01   #13
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
Bonjour et merci pour ta réponse détaillée.

Je viens de créer ce script, donc, la lenteur, c'est depuis la 1ère exécution.
En local, cela va un peu plus vite, mais c'est pas terrible.
Mais je devrais dire "c'était", car le simple fait d'utiliser JOIN à la place de LEFT OUTER JOIN a divisé le temps par 4 ! Bon à savoir.

J'ai tenté d'utiliser Firebug, mais mon FF ne l'apprécie pas du tout...
Et, oui j'ai fait des optimize sur les tables concernées.

Cette partie de mon post est donc résolue. J'ai ensuite posé une seconde question concernant la requête elle-même et comment éviter les doublons dans l'affichage qui se produisent même avec DISTINCT.

Bonne journée.
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2011, 10h56   #14
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Citation:
Mais je devrais dire "c'était", car le simple fait d'utiliser JOIN à la place de LEFT OUTER JOIN a divisé le temps par 4 ! Bon à savoir.
C'est bon à savoir effectivement.

En tout cas, de mon coté je privilégie toujours une jointure stricte (JOIN), car dans la majorité des cas on ne souhaite pas obtenir les données NULL ou non présentes par rapport à la jointure.

Disons qu'il faut percevoir ça comme non pas une optimisation, mais bel et bien de 2 besoins/résultat potentiellement différents, donc l'un ne remplace pas l'autre.

Mais même divisé par 4, ça sous entend que ça fait 5 secondes, ça me semble encore beaucoup.
Il y a peut être beaucoup de catégories.
C'est quand même bizarre, car MySQL est théoriquement capable de travailler avec plusieurs milliers de lignes, sans pourtant prendre plusieurs secondes pour 1 (petite) requête.

As tu des INDEX au niveau de la table "categories" et "produits" ?


Citation:
J'ai ensuite posé une seconde question concernant la requête elle-même et comment éviter les doublons dans l'affichage qui se produisent même avec DISTINCT.
Si je ne dis pas de bêtise, un GROUP BY p.id devrait faire l'affaire.

Toujours si je ne dis pas de bêtise, le DISTINCT agit uniquement sur les valeurs des champs au niveau du SELECT, et élimine les doublons si tous les noms identiques.

DISTINCT ne fonctionne pas car le nom du champ c.nom est différent pour chaque p.id, même pour 2 ou 3, etc ... p.id identiques.
Normal, un produit est lié à plusieurs catégories différentes, donc de nom de catégories différentes.

En utilisant un GROUP BY, on désigne explicitement le ou les champs où doivent s'appliquer le regroupement.
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2011, 13h14   #15
Membre confirmé
 
Avatar de renaud26
 
Inscription : mars 2003
Messages : 1 043
Détails du profil
Informations personnelles :
Âge : 48
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : mars 2003
Messages : 1 043
Points : 285
Points : 285
Merci RunCodePhp !

C'est exactement ça : étant donné que dans la table produits_categories j'ai un doublon sur le champ produit_id, j'ai fait un GROUP BY pc.produit_id et c'est nickel.

Encore merci et bonne journée.
renaud26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h06.


 
 
 
 
Partenaires

Hébergement Web