Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1564 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Optimisation d'une requete

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Optimisation d'une requete

n°1769454
cartouche3​1
Posté le 05-08-2008 à 13:07:41  profilanswer
 

Bonjour,
 
J'ai un site qui ralentit à l'execution d'une requete :  
 

Code :
  1. "SELECT fights.*, p1.name AS att, p2.name AS def, p1.idpet AS attPic, p2.idpet AS defPic  FROM fights
  2.       LEFT JOIN (SELECT pets.id, pets.name, pets.idpet
  3.          FROM pets ) AS p1 ON fights.id_off=p1.id
  4.       LEFT JOIN (SELECT pets.id,pets.name, pets.idpet
  5.          FROM pets) AS p2 ON fights.id_def=p2.id
  6.       LEFT JOIN pets ON fights.id_off=pets.id
  7.       WHERE fights.etat = 0 AND pets.owner=".$id." ORDER BY time DESC LIMIT ".$page.",".$limit);


 
Les deux tables consultes sont pets ( plus de 100 000 lignes ) et fights ( environ 6000 lignes ). Or mon hebergeur m'a dit que cette requete faisait consulter environ 1 million de lignes au total ce qui fait ralentir tout mon site.
 
Avez vous une idée pour l'optimiser voir la découper en deux pour qu'à la fin je puisse récupérer les données suivantes :  
 
att
def
attPic
defPic
 
Merci de votre aide :)

mood
Publicité
Posté le 05-08-2008 à 13:07:41  profilanswer
 

n°1769464
casimimir
Posté le 05-08-2008 à 13:31:46  profilanswer
 

1) vérifier que tu as bien un index sur pets.id
 
2) en oracle ca ne changerait rien mais peut-etre que en mysql ca a son importance, il n'y a pas d'interet a sous-selecter tes tables pets
 
en plus en le réécrivant on peut voir que tu attaques 2x pets en outer join sur le champ fights.id_off
encore une rajoute en relisant, si tu mets pets.owner dans ton where, alors c'est un inner join

Code :
  1. "SELECT fights.*, p1.name AS att, p2.name AS def, p1.idpet AS attPic, p2.idpet AS defPic  FROM fights
  2.          LEFT JOIN pets  AS p1 ON fights.id_off=p1.id
  3.          LEFT JOIN pets AS p2 ON fights.id_def=p2.id
  4.          LEFT JOIN pets as p3 ON fights.id_off= p3.id
  5.          WHERE fights.etat = 0 AND pets.owner=".$id." ORDER BY time DESC LIMIT ".$page.",".$limit);


Message édité par casimimir le 05-08-2008 à 13:32:28
n°1769514
MagicBuzz
Posté le 05-08-2008 à 14:10:39  profilanswer
 

malgré la réécriture faite par casimimir, il reste un souci de produit cartésien au niveau de ta troisième occurence de pets.
 
t'as un filtre sur le owner_id mais c'est tout. à mon avis y'a une couille dans le potage...
 
tu essaies de faire quoi au juste ?


Message édité par MagicBuzz le 05-08-2008 à 14:10:55
n°1769724
cartouche3​1
Posté le 05-08-2008 à 17:52:02  profilanswer
 

En fait le joueur lance un combat contre un autre joueur avec un de ses animaux pets. Une fois le combat lancé, cela lance cette requête pour affiché sur une page les combats lances.
 
On se retrouve ainsi avec deux colonnes : dans une colonne, l'image, le nom du pets qui a lancé le combat, et dans l'autre colonne l'image et le nom du pets contre lequel on a lancé le combat.
 
Les combats sont triés par date.
 
Seul les combats lances et pas encore acceptés ( etat = 0 ) sont affichés.

n°1769729
MagicBuzz
Posté le 05-08-2008 à 17:57:33  profilanswer
 

et ça donne quoi en shootant ton p3 et en mettant "and (p1.owner = $id or p2.owner = $id)" ?

n°1769747
cartouche3​1
Posté le 05-08-2008 à 18:11:16  profilanswer
 

J'obtient des pages blanches sur mon site si je fais ca.

n°1769956
bruno2607
Posté le 06-08-2008 à 09:42:58  profilanswer
 

Bonjour
 
je pense que la condition 'LEFT JOIN pets as p3 ON fights.id_off= p3.id' ne sert a rien
et que la condition pets.owner=".$id." est erroné, elle ne fait pas référence à la table P1 ou P2 !!!
 
que se passe t'il si tu execute la requete suivante
 

Code :
  1. SELECT fights.*, p1.name AS att, p2.name AS def, p1.idpet AS attPic, p2.idpet AS defPic  FROM fights
  2.    LEFT JOIN pets  AS p1 ON fights.id_off=p1.id AND p1.owner=".$id
  3.    LEFT JOIN pets AS p2 ON fights.id_def=p2.id AND p2.owner=".$id
  4.    WHERE fights.etat = 0
  5.    ORDER BY time DESC LIMIT ".$page.",".$limit);


 
Bruno

n°1770012
cartouche3​1
Posté le 06-08-2008 à 10:36:02  profilanswer
 

Ben ca me donne toujours une page blanche.
 
Il faut savoir que la première requete que j'ai donné est bonne, le site fonctionne avec mais il ralentit de trop depuis une semaine car une table est devenue trop grosse apparement.
 
Et à chaque fois que je change la requete avec vos modifs, j'obtient une page blanche à la place :(

n°1770037
HappyHarry
Posté le 06-08-2008 à 10:49:18  profilanswer
 

pareil que magicbuzz, moi je l'aurais écrite comme ca  
 

Code :
  1. SELECT  fights.*,
  2.  p1.name AS att,
  3.  p2.name AS def,
  4.  p1.idpet AS attPic,
  5.  p2.idpet AS defPic 
  6. FROM  fights
  7.  INNER JOIN pets p1 on fights.id_off=p1.id
  8.  INNER JOIN pets p2 ON fights.id_def=p2.id
  9. WHERE  fights.etat = 0
  10.  AND (p1.owner=".$id." or p2.owner=".$id." )
  11. ORDER BY time DESC


Message édité par HappyHarry le 06-08-2008 à 10:49:37
n°1770080
casimimir
Posté le 06-08-2008 à 11:39:27  profilanswer
 

a mon avis vu ce qu'il explique il ne faut pas de or, car il ne veut que les combats que le joueur a lancé, je suppose que id_off c'est pour id_offender et id_def pour id_defender, donc a priori le where doit cibler uniquement p1.
 
de nouveau je connais assez peu mysql mais un plan d'exécution ca éviterait 14 posts
 
ca c'est le plus logique par rapport a ton truc:
 

Code :
  1. SELECT  fights.*,
  2.   p1.name AS att,
  3.   p2.name AS def,
  4.   p1.idpet AS attPic,
  5.   p2.idpet AS defPic
  6. FROM  pets p1
  7. INNER JOIN fights f on f.id_off=p1.id
  8. INNER JOIN  on pets p2 ON f.id_def=p2.id
  9. WHERE p1.owner=".$id."
  10. and f.etat = 0
  11. ORDER BY time DESC


 
mais le vraiment plus logique serait un truc genre
 

Code :
  1. SELECT  fights.*,
  2.   p1.name AS att,
  3.   p2.name AS def,
  4.   p1.idpet AS attPic,
  5.   p2.idpet AS defPic
  6. FROM  owner o
  7. INNER JOIN fights f on f.id_off=o.id
  8. INNER JOIN pets p1 f.id_off=p1.id
  9. INNER JOIN pets p2 f.id_def=p2.id
  10. WHERE o.owner=".$id."
  11. and f.etat = 0
  12. ORDER BY time DESC


 
dans tous les cas, vérifier que tu as des index ou il faut


Message édité par casimimir le 06-08-2008 à 11:41:35
mood
Publicité
Posté le 06-08-2008 à 11:39:27  profilanswer
 

n°1770081
cartouche3​1
Posté le 06-08-2008 à 11:39:31  profilanswer
 

HappyHarry, je viens de mettre ta requete en place. Ca a l'air de fonctionner avec cependant un petit bug d'affichage car on a occulté cette ligne : LEFT JOIN pets ON fights.id_off=pets.id .
 
Du coup au lieu d'avoir que les combats lances, on se retrouve avec les lances et les recus sur la même page.
 
Dommage car sinon ca a l'air bien plus rapide. Saurait tu comment remettre cette ligne de code dans celui que tu m'as livré en dernier ?

n°1770085
cartouche3​1
Posté le 06-08-2008 à 11:42:15  profilanswer
 

casimimir, le owner du pets est dans la table des pets. Ce n'est pas une table en soit. Sinon oui tu avais bien cerné le fait que je ne voulais que les combats lances, on a posté en même temps.

n°1770179
HappyHarry
Posté le 06-08-2008 à 14:17:36  profilanswer
 

cartouche31 a écrit :

HappyHarry, je viens de mettre ta requete en place. Ca a l'air de fonctionner avec cependant un petit bug d'affichage car on a occulté cette ligne : LEFT JOIN pets ON fights.id_off=pets.id .
 
Du coup au lieu d'avoir que les combats lances, on se retrouve avec les lances et les recus sur la même page.
 
Dommage car sinon ca a l'air bien plus rapide. Saurait tu comment remettre cette ligne de code dans celui que tu m'as livré en dernier ?


 
si effectivement tu veux distinguer les combats "lancés" et "reçus", réfère toi à ce que te propose casimimir

n°1770559
bruno2607
Posté le 07-08-2008 à 10:58:34  profilanswer
 

Bonjour  
Que donne ces 2 requetes ?
 

Code :
  1. SELECT fights.*, p1.name AS att, p2.name AS def, p1.idpet AS attPic, p2.idpet AS defPic  FROM fights
  2. INNER JOIN pets  AS p1 ON fights.id_off=p1.id AND p1.owner=".$id
  3. LEFT JOIN pets AS p2 ON fights.id_def=p2.id
  4. WHERE fights.etat = 0
  5. ORDER BY time DESC LIMIT ".$page.",".$limit)


 

Code :
  1. SELECT fights.*, p1.name AS att, p2.name AS def, p1.idpet AS attPic, (select p2.idpet from pets AS p2 where fights.id_def = p2.id) AS defPic  FROM fights
  2. INNER JOIN pets  AS p1 ON fights.id_off=p1.id AND p1.owner=".$id
  3. WHERE fights.etat = 0
  4. ORDER BY time DESC LIMIT ".$page.",".$limit)


n°1770746
cartouche3​1
Posté le 07-08-2008 à 15:12:30  profilanswer
 

Aucune des deux ne fonctionne bruno2607 :(  
 
Mais bon c'est pas grave pour le moment le site tourne rapidement avec la requete de HappyHarry et même si ca n'affiche pas que les defis lancés, c'est pas trop genant car ce n'est pas une page critique, en plus les joueurs savent quels sont leur combattant et ceux des adversaires dans la liste. L'important est que ca soit rapide et que ca fasse presque comme avant :)  
 
Merci à tous de votre aide en tout cas, c'est sympa de votre part et franchement ca m'a vraiment aidé car mon site était un peu bloqué a cause de ca.

n°1770838
HappyHarry
Posté le 07-08-2008 à 16:35:20  profilanswer
 

Code :
  1. Code :
  2.    1. SELECT  fights.*,
  3.    2.  p1.name AS att,
  4.    3.  p2.name AS def,
  5.    4.  p1.idpet AS attPic,
  6.    5.  p2.idpet AS defPic
  7.    6. FROM  fights
  8.    7.  INNER JOIN pets p1 on fights.id_off=p1.id
  9.    8.  INNER JOIN pets p2 ON fights.id_def=p2.id
  10.    9. WHERE  fights.etat = 0
  11.   10.  AND p1.owner=".$id."
  12.   11. ORDER BY time DESC


 
pour n'avoir que les défis lancés par le joueur

n°1770992
rosco
Posté le 08-08-2008 à 00:20:25  profilanswer
 

Fais déjà un EXPLAIN de ta requête d'origine pour voir d'où peut venir le problème de perf, c'est là pour ça...


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Optimisation d'une requete

 

Sujets relatifs
optimisation de requéteProbleme et optimisation de requete
[SQL] Optimisation de requete[SQL] Optimisation d'une réquète récursive
[SQL] Optimisation de requête "regroupement X-en-1" (tri ?)Optimisation requête (Mysql)
MySQL - Optimisation d'une requête avec plusieurs JOIN[Oracle ASM] Problème d'optimisation de requête suite à migration
[Oracle] Optimisation d'une requête de mise à jour[ORA] - Optimisation d'une requete
Plus de sujets relatifs à : Optimisation d'une requete


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR