Exécution trop lente de requète

Résolu
msi79 Messages postés 509 Date d'inscription lundi 24 août 2009 Statut Membre Dernière intervention 2 mai 2023 - Modifié par jordane45 le 28/09/2014 à 23:29
jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 - 30 sept. 2014 à 10:33
Bonjour,
ma page de cesse de tourner quand j'exécute ma requête .
il y a t il une autre méthode ??
                
$sql = "SELECT *
FROM victime V
,prejudicemoraux PM
,agent AG
,tb_departement DPTD
,tb_sous_prefecture SPD
,tb_commune COMD
,tb_localite LCD
,prejudicemateriel PMAT
,infogenerale IG
,tb_parent P
WHERE $critere
AND V.matricule = PM.id_prejM
AND PM.id_prejM = AG.id
AND AG.id = DPTD.id
AND DPTD.id = SPD.id
AND SPD.id = COMD.id
AND COMD.id = LCD.id
AND LCD.id = PMAT.id_prejMat
AND PMAT.id_prejMat = IG.id_infoG
AND IG.id_infoG = P.id
ORDER BY V.nomV
";

6 réponses

jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 344
28 sept. 2014 à 23:31
Bonjour,

Oui... en passant par des jointures INNER JOIN ou LEFT JOIN..
Et puis.. tout dépend aussi de ce que contient ta variable $criteres...

Par contre, es-tu sûr que le souci vienne de la requête ( tu l'as testé en direct dans ta BDD ?? ) ou de son traitement dans son code php ??

PS: Pourquoi.... alors que tu poses une question sur une REQUETE SQL ... tu poses ta question dans PHP ????
(ce n'est pas la première fois que je te fais cette remarque ! )





0
msi79 Messages postés 509 Date d'inscription lundi 24 août 2009 Statut Membre Dernière intervention 2 mai 2023 1
28 sept. 2014 à 23:44
en direct exécution de la requête donne rien
0
jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 344
29 sept. 2014 à 00:01
La requête à tester....est celle que tu récupères via un echo bien sûr. ...
0
mpmp93 Messages postés 6652 Date d'inscription mercredi 13 avril 2011 Statut Membre Dernière intervention 28 septembre 2015 4
29 sept. 2014 à 11:39
Bonjour,

je connais ce genre de problème.....

D'une part, si la volumétrie de données est importante, il faut déja limiter le nombre de fiches. Donc faire un LIMIT, exemple:

LIMIT 0,20


à rajouter dans le code SQL va limiter à 20 fiches....


Ensuite, piège très grossier dans lequel beaucoup tombent, même des pros en BDD, c'est oublier d'indexe les champs sur lesquels on fait des WHERE.

Par exemple, dans votre code SQL, je vois ceci:

WHERE $critere  


Si un des critères est par exemple date_des_faits, il faut que ce champ soit indexé.

Enfin, je vois que vous utilisez des alias de noms de tables:

FROM victime V
,prejudicemoraux PM
,agent AG
,tb_departement DPTD
,tb_sous_prefecture SPD
,tb_commune COMD
,tb_localite LCD
,prejudicemateriel PMAT
,infogenerale IG
,tb_parent P


C'est très bien pour la lisibilité, mais il faudrait gérer les jointures entre ces tables avec INNER JOIN et les index primaires.

Attention, trop de jointures "flinguent" les performances, voire déconnectent des données.

Je serai à votre place, je ferai ceci:

SELECT *
            FROM victime V
WHERE $critere   
 ORDER BY V.nomV
LIMIT 0,20


afin de sortir 20 fiches respectant vos critères (champs indexés évidemment). Ensuite, vous affichez le minimum syndical à l'écran et ensuite, quand on veut voir une fiche, là vous allez piocher dans les différentes tables ce qui est nécessaire pour voir la fiche en détail.

Performance maximale assurée...

A+
0
jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 344
29 sept. 2014 à 12:02
@mpm :

Indexer les champs : Oui (j'avais oublié de lui dire).

Utiliser les Jointures : Oui (je lui ai dit)

Utiliser des "LIMITES" .. mouais... pourquoi pas... Mais dans ce cas.. il est plus propre d'utiliser de la pagination... mais là.. c'est un autre sujet.

Ensuite, vous affichez le minimum syndical à l'écran et ensuite, quand on veut voir une fiche, là vous allez piocher dans les différentes tables ce qui est nécessaire pour voir la fiche en détail.
[...]
Performance maximale assurée...
Pas nécessairement... tout dépend de ce qu'il veut avoir à l'écran....et comment il l'affiche.
Si il découpe son affichage en plusieurs "vues" du genre :
Un tableau contenant le strict minimum ... puis si on clique sur la ligne d'un ticket.. on affiche les infos de se ticket (et donc.. seulement à ce moment là on va requêter la BDD pour en récupérer le contenu...) là.. oui.....
Mais connaissant MSI et sa façon de coder et la manière dont il présente le contenu de ses pages... à mon avis.. ça ne lui correspondra pas...


Sans oublier ...Pour gagner en performance.. il faut aussi limiter les SELECT * et ne faire un SELECT que des champs nécessaires...

Et enfin... tout dépend également de ce qu'il a dans son WHERE.
Si le WHERE contient des conditions sur des champs TEXTE (ou varchar).. la requête sera forcément plus longue que sur des champs numériques....

Bref...

Déjà... il faut, pour s'assurer que le souci vient de la requête, et non pas de son traitement lors de l'affichage des données dans la page PHP.. qu'il teste sa requête en direct dans la BDD ...
( 1 - Faire un ECHO de la requête dans la page PHP
2 - Prendre cette requête ainsi générée et la tester directement dans la BDD
3 - Regarder combien de temps elle met....)
=> Perso.. si elle met plus de 2 voir 3 secondes (et encore.. je suis large)... c'est clair que la lenteur vient d'elle.....
=> Sinon... le souci vient du traitement dans la page !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
msi79 Messages postés 509 Date d'inscription lundi 24 août 2009 Statut Membre Dernière intervention 2 mai 2023 1
29 sept. 2014 à 12:30
bonjour @mpmp93. merci de bien vouloir m'aider .
au fait au départ c'est ce que j'avais fait :
SELECT *
FROM victime V
WHERE $critere
ORDER BY V.nomV
LIMIT 0,20
mais il se trouve que quand je dois afficher par exemple la liste des blessés ou le critère se trouve dans une autre tables j'arrive pas .
0
mpmp93 Messages postés 6652 Date d'inscription mercredi 13 avril 2011 Statut Membre Dernière intervention 28 septembre 2015 4
Modifié par mpmp93 le 29/09/2014 à 16:51
Je regrette de pas être à coté de vous pour comprendre exactement le fonctionnement de votre BDD et votre besoin exact et vous piloter. C'est jamais facile avec des fragments d'infos.

Le problème, c'est que dans votre

SELECT *

on ne sait pas ce que vous sortez: des IDs? des noms? des villes? etc....

Comme la table s'appelle 'victime' je suppose que ce sont des victimes d'accidents ou de voies de faits....

Donc, supposons que vous ayez les noms dans PM, il faut faire une jointure:


SELECT *
            FROM victime V
            INNER JOIN prejudicemoraux PM
            ON V.matricule  = PM.id_prejM
WHERE $critere   
 ORDER BY V.nomV
LIMIT 0,20
V.matricule  = PM.id_prejM


et remplacez, svp

SELECT *


par

SELECT V.champ1, V.champ2..... PM.champ1, PM.champ2


en clair, limitez les champs après SELECT à ceux nécessaires pour la liste générale.

Comme je l'avis précisé avant, il est impératif que les champs en jointure et les champs testés par WHERE soient indexés: index ordinaire, unique ou primaire

Cette histoire d'indexation que beaucoup oublient.... J'ai connu un BAC+6 qui gérait une base de plus de 10Go. Chaque requête prenait plus d'une heure.... Il a tout essayé: myIsam et autres modèles de gestion... Rien n'y faisait. Trois semaines de cauchemar pour lui.

Je passe dans son dos. il râle, je lui pose la question: Késkilya? Il m'esplique. Montre-moi ta structure.... Tiens, tu fais un WHERE sur une date non indexée.

Il me répond, si j'indexe, je grossis la base et ça va prendre une plombe. J'insiste et ré-insiste. Il index la date. 3 minutes. Il re-teste la requête qui prennait plus d'une heure.... 35 secondes!

Authentique!

Bon il a pas pu s'arracher les cheveux, il était déja quasi-chauve.... mais le chauve sourit, et me remercia.

C'est devenu un cas d'école chez nous.

A+
0
mpmp93 Messages postés 6652 Date d'inscription mercredi 13 avril 2011 Statut Membre Dernière intervention 28 septembre 2015 4
29 sept. 2014 à 16:53
PS: si INNER JOIN marche pas, faites un LEFT JOIN

Blague: le JOIN ne se fume pas....
0
msi79 Messages postés 509 Date d'inscription lundi 24 août 2009 Statut Membre Dernière intervention 2 mai 2023 1
Modifié par jordane45 le 30/09/2014 à 09:14
Comment transformer cette requète en utilisant INNER JOIN . Je maitrise pas cette methode
  $sql = "SELECT * 
FROM victime V
,prejudicemoraux PM
,agent AG
,tb_departement DPTD
,tb_sous_prefecture SPD
,tb_commune COMD
,tb_localite LCD
,prejudicemateriel PMAT
,infogenerale IG
,tb_parent P
WHERE $critere
AND V.matricule = PM.id_prejM
AND PM.id_prejM = AG.id
AND AG.id = DPTD.id
AND DPTD.id = SPD.id
AND SPD.id = COMD.id
AND COMD.id = LCD.id
AND LCD.id = PMAT.id_prejMat
AND PMAT.id_prejMat = IG.id_infoG
AND IG.id_infoG = P.id
ORDER BY V.nomV LIMIT 0,20
";
0
jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 344
29 sept. 2014 à 23:57
Est ce que tu as cherché un minimum au moins ??
0
msi79 Messages postés 509 Date d'inscription lundi 24 août 2009 Statut Membre Dernière intervention 2 mai 2023 1
30 sept. 2014 à 00:09
OUI J'AI TENTE CA MARCHE PAS JE CROIS QUE JE ME MÉLANGE VU QUE IL Y A TROP DE TABLES
0
jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 344
Modifié par jordane45 le 30/09/2014 à 09:17
OUI J'AI TENTE CA MARCHE PAS JE CROIS QUE JE ME MÉLANGE VU QUE IL Y A TROP DE TABLES
Et tu penses que si tu ne nous montres pas ce que tu as essayé de faire que nous allons pouvoir t'aider à corriger ??

Nb : juste pour info :
Pour créer/tester ses requêtes...il faut le faire en direct dans la BDD (pas dans ta page PHP)....


Je te donne la première jointure :

SELECT * 
 FROM victime V
 LEFT JOIN prejudicemoraux PM ON  V.matricule  = PM.id_prejM



A toi de compléter...

NB² : Pense que L'ordre des Jointures dépend de la structure de ta table et des infos que tu souhaites avoir dans ta requête...donc commence par tester une première jointure... puis si elle te donne le résultat attendu..ajoute la secode..etc...


Avant de poser une question, merci de lire la charte du site.
Cordialement, Jordane
0
mpmp93 Messages postés 6652 Date d'inscription mercredi 13 avril 2011 Statut Membre Dernière intervention 28 septembre 2015 4
30 sept. 2014 à 10:31
Pour créer/tester ses requêtes...il faut le faire en direct dans la BDD (pas dans ta page PHP)....

Je rajouterai que "le faire en direct", c'est à dire via phpMyAdmin.... -> onglet SQL et saisir sa requête SQL à la main, puis cliquer sur "exécuter"
0
jordane45 Messages postés 38138 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 17 avril 2024 344
30 sept. 2014 à 10:33
Ou encore mieux... via des logiciels comme HeidiSQL...
http://codes-sources.commentcamarche.net/faq/10778-heidisql-tester-ses-requetes-sql
0
Rejoignez-nous