[PHP] Requête très lente

Nouveau WRInaute
Bonsoir,

Je suis actuellement, en train de développer un jeu par navigateur.
J'utilise une fonction PHP qui permet de me retourner le nombre de serf/artisan qui travail (selon l'accréditation qui lui a été donné).

Voici la fonction
PHP:
<span class="syntaxdefault"><br />function getNumbPop</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">$joueur</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">$accreditation</span><span class="syntaxkeyword">)<br />{<br /></span><span class="syntaxdefault">    global $bdd</span><span class="syntaxkeyword">;<br /><br /></span><span class="syntaxdefault">    $cout </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> $bdd</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">prepare</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"SELECT COUNT(id) FROM population WHERE joueur= :joueur AND accreditation= :accreditation"</span><span class="syntaxkeyword">);<br /></span><span class="syntaxdefault">    $cout</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">bindValue</span><span class="syntaxkeyword">(</span><span class="syntaxstring">':joueur'</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> $joueur</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> PDO</span><span class="syntaxkeyword">::</span><span class="syntaxdefault">PARAM_INT</span><span class="syntaxkeyword">);<br /></span><span class="syntaxdefault">    $cout</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">bindValue</span><span class="syntaxkeyword">(</span><span class="syntaxstring">':accreditation'</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> $accreditation</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> PDO</span><span class="syntaxkeyword">::</span><span class="syntaxdefault">PARAM_STR</span><span class="syntaxkeyword">);<br /></span><span class="syntaxdefault">    $cout</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">execute</span><span class="syntaxkeyword">();<br /></span><span class="syntaxdefault">    return $cout</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">fetchColumn</span><span class="syntaxkeyword">();<br />}<br /></span><span class="syntaxdefault"> </span>

Si j'appel la fonction une fois dans la page, celui-ci me retourne 0.2400 secondes, tandis que si je l'utilise 24 fois (vu que j'ai 24 ressources différentes), ça met plus de 5 secondes à m'afficher les résultats.
J'ai fait le test sur une table qui avait plus de 400.000 résultats.

Y'aurait-il une solution pour régler ce soucis ?

Cordialement,
 
WRInaute accro
HeLiArK a dit:
ça met plus de 5 secondes à m'afficher les résultats.
5.76 secondes par hasard ? ou est le problème ?

Faut que tu repense le truc pour ne passer qu'une seule requête sur ta table (peut être avec du group by par exemple)
 
Nouveau WRInaute
Salut,

spout a dit:
J'ai essayé EXPLAIN sous phpmyadmin, il me retournait "ALL" en type... J'ai réussie à le faire passer en type "ref"

zeb a dit:
HeLiArK a dit:
ça met plus de 5 secondes à m'afficher les résultats.
5.76 secondes par hasard ? ou est le problème ?

Faut que tu repense le truc pour ne passer qu'une seule requête sur ta table (peut être avec du group by par exemple)

Et oui, aux environs de 5.76 secondes ^^
Le problème c'est que la requête est très lente...
Oui, c'est ce que je cherche à faire... Avec qu'une seule requête... Mais bon, je suis à court d'idée donc ^^
Sinon, avec GROUP BY ça met plus de 2 secondes pour retourner un résultat...

Si vous avez d'autres propositions je suis preneur...
 
WRInaute accro
HeLiArK a dit:
avec GROUP BY ça met plus de 2 secondes pour retourner un résultat...
D'un autre côté requête sur des truc multiples avec obligation de regrouper ça va forcement chiffrer. As tu essayé de poser des index sur tes champs de travail pour faciliter le travail. Faut aussi voir si tu peux changer la nature des champs travaillés, chercher des chaînes de caractère équivalentes est beaucoup moins performant que tester l'égalité d'un entier.
 
WRInaute accro
Tu as bien un index sur joueur et accreditation (un sur les deux, pas un sur chaque) dans ta table population?

Sinon effectivement ce serait une bonne idée de grouper tout ça en une seule requête avec un GROUP BY, et mettre le résultat dans un tableau associatif, ça évitera pas mal de latence, de parsing et de planning.

Jacques.
 
Nouveau WRInaute
Salut,

zeb a dit:
HeLiArK a dit:
avec GROUP BY ça met plus de 2 secondes pour retourner un résultat...
D'un autre côté requête sur des truc multiples avec obligation de regrouper ça va forcement chiffrer. As tu essayé de poser des index sur tes champs de travail pour faciliter le travail. Faut aussi voir si tu peux changer la nature des champs travaillés, chercher des chaînes de caractère équivalentes est beaucoup moins performant que tester l'égalité d'un entier.

Oui, j'ai posé des index sur mes champs...
J'essaie au maximum de bosser avec des entiers, mais bon...
 
WRInaute accro
Encore une fois, un index sur les deux colonnes, pas un index sur chaque (si tu fais une requête par accreditation plutôt qu'une seule grosse requête avec un GROUP BY).

Je ne comprends pas ton commentaire sur les entiers? Oui, c'est logique et bien d'utiliser des entiers, qu'est-ce-qui a été dit qui irait en sens contraire?

Jacques.
 
WRInaute accro
jcaron a dit:
qu'est-ce-qui a été dit qui irait en sens contraire?
Ma remarque qui était dans le sens de lui conseiller l'usage d'entiers (au cas où ce n'était pas le cas) dans ses champs plutôt que des chaines de caractères pour éviter des lenteurs de comparaison.
 
Nouveau WRInaute
jcaron a dit:
Encore une fois, un index sur les deux colonnes, pas un index sur chaque (si tu fais une requête par accreditation plutôt qu'une seule grosse requête avec un GROUP BY).

J'ai mit les index seulement sur les deux colonnes.
 
WRInaute accro
Je crois qu'on ne se comprend toujours pas... Tu peux avoir tous les autres index que tu veux suivant tes besoins, mais tu as besoin d'un index composite sur les deux colonnes (par opposition à deux index chacun sur une colonne):
Code:
CREATE INDEX population_joueur_accreditation_idx ON population(joueur,accreditation);

Par opposition à:
Code:
CREATE INDEX population_joueur_idx ON population(joueur);
CREATE INDEX population_accreditation_idx ON population(accreditation);

Suivant le nombre de lignes qui correspondent à l'un ou l'autre, ça peut faire une différence importante.

Jacques.
 
Nouveau WRInaute
Avec cet Index, je passe à 1.500s (environ).

Bon, je ne pense pas que l'on puisse réduire encore ce temps...

Donc, merci ;).
 
WRInaute accro
Il y a quelque chose de pas très net dans ta base... Avec les données en cache c'est de la requête qui prend moins d'une milliseconde, et quand les données ne sont pas en cache ça ne devrait pas dépasser quelques dizaines de ms, à moins que ton serveur soit surchargé au niveau I/O et/ou que ta base soit vraiment énorme.

Tu as combien de lignes dans cette table, combien de joueurs, combien d'accréditations par joueur (et/ou combien de lignes population en moyenne par joueur)? J'ai fait le test sur une table de 10 millions de lignes (1000 joueurs, 100 accréditations, 100 lignes par combinaison), et ça passe comme une lettre à la poste. Alors c'est plus facile dans mon cas parce que la table est "bien rangée" (donc toutes les lignes intéressantes sont très proches les unes des autres), mais avec un cache un tantinet efficace et une machine qui n'est pas saturée en I/O ça ne devrait pas poser de problème particulier...

Jacques.
 
Nouveau WRInaute
Voilà comment est ma base:

id int AI
joueur int
type varchar
accreditation varchar

Sinon, j'ai un peu plus de 400.000 lignes dans la table...

Je suis le seul étant donné qu'il est en local. Le nombre d'accréditation, ça peut déprendre... Il n'y a pas de limite en faite... Tu peux en avoir 100 comme 600...
 
WRInaute accro
1.5 secondes (ou même 240 ms) pour une requête comme ça sur une table de cette taille c'est anormal si les index sont bons et effectivement utilisés et que ta machine ne sature ni en RAM (ce qui invaliderait les caches très vite) ni en I/O.

Avec les données en cache c'est une histoire de millisecondes, voire moins. Si tout n'est pas en cache (mais les premiers niveaux des btrees doivent le rester si ta machine n'est pas complètement à la ramasse), on parle de quelques dizaines de ms suivant la fragmentation de la table.

Donc soit tu manques de RAM, soit tu satures complètement en I/O (ce qui serait une conséquence logique du premier cas), soit tu as un problème de config...

Ca donne quoi "top" et "ps -ef" sur la machine? Il y a combien de RAM et quoi qui tourne dessus?

Jacques.
 
Nouveau WRInaute
Salut,

Désolé, je n'avais pas vu ta réponse...

Je reviendrai plus tard pour répondre à tes questions, faut que je demande à mon chef de projet s'il a accès à SSH ou pas ainsi demander les caractéristiques du serveur...

Cordialement,
 
Nouveau WRInaute
Salut,

Sur le serveur, il y a 1Go de RAM, aucun accès SSH. On est chez OVH, linux la distribution n'est pas indiquée oO...

Cordialement,
 
Discussions similaires
Haut