TourDeJeu, le réseau des jeux en ligne alternatifs : jeux web multijoueurs, jeux par forum. En savoir +

Flux RSS des discussions du forum : pour les joueurs, et pour les créateurs et MJ
  Reply to this topicStart new topicStart Poll

> Temps De Chargement
Vanth
Ecrit le : Mercredi 12 Octobre 2005 à 23h26
Quote Post


Kid
*

Groupe : Membre
Messages : 16


Salut à tous.
J'aurai une question bêbête :

Combien de temps, avec un serveur je dirai "standart" (un truc bien, sans plus) prend une selection de données de 50 champs dans une base de données ? (sans grosse optimisation de bourrin d'SQL, j'en suis pas encore à là ^^)

Ca peut paraitre bizarre comme question, mais dans la mesure ou le jeu que je programme est assez "lourd" niveau nombres de variables, j'aimerai savoir si cela pourrait poser un problème lors du chargement des pages, des requetes ect...

Autre question, plus par curiosité celle ci :
Y a t'il une différence dans le temps de chargement (ne serai minim) entre :

SELECT var1, var2 FROM database..

et :

SELECT var1 FROM database
SELECT var2 FROM database

A part que la deuxième écriture est plus lourde, moche et Cie, y a t'il une différence lors de l'exécution ?
PMEmail Poster
Top
Haram turval
Ecrit le : Mercredi 12 Octobre 2005 à 23h46
Quote Post


Pro
*

Groupe : Membre
Messages : 126


Ouf.. large question s'il en est.
Les performances peuvent dépendre de tellement de choses :
Qualité du serveur
Qualité du code
Type de requête
Nombre de connectés
Taille du résultat de la reqête
etc

Mais bon, pour répondre à ta question, je conseillerai la solution 1, tout simplement pour limiter le nombre de requêtes lancées sur le serveur SQL.

en effet, que tu fasse
select var1, var2, from table
ou
select var1 from table
select var2 from table
tu ramènes var 1 ET var2.

Autant tout ramener en une fois, cela ne fera qu'une seule requête.


--------------------
Tant va la cruche à l'eau qu'à la fin elle est mouillée.
PMEmail Poster
Top
Stabbquadd
Ecrit le : Jeudi 13 Octobre 2005 à 00h34
Quote Post


Pro
*

Groupe : Membre
Messages : 76


Le temps demandé pour selectionner 50 champs dépend de quantité de choses en effet. Si tu permets, je vais te donner quelques conseils simples sur les erreurs à ne pas faire pour que ce temps soit réduit au maximum. Ce sont souvent des erreurs que j'ai fait par le passé, en suivant des tutoriels bancals (j'ai appris la programmation à l'aide de ces même tutoriels et de nombreux tests et tâtonnements :s).

En fait je pense que le plus important n'est pas en combien de fois tu vas récupérer tes données, même si le plus petit nombre de fois est forcément la meilleure solution, mais surtout la quantité de selections que tu va faire.

Par exemple si tu veux récupérer les données de l'enregistrement qui a le plus de var1, il peut t'arriver de faire ceci :
"SELECT * FROM table WHERE 1 ORDER BY var1 DESC"
(je l'ai déjà vu, c'est même dans certains tutoriels !!!)
Pendant les tests, tout va bien se passer, mais dès que tu auras ne serait-ce que 100 joueurs ca va commencer à ramer !
Pourquoi ? Mais parce que non seulement tu sélectionnes TOUS les champs de ta table, mais en plus pour chacun tu fais un test ("WHERE 1"). Ainsi ca équivaut à ce que ta base de données parcourt 2 fois l'intégralité de ta table, et si tu as 5000 enregistrements, ca fait 10000 opérations.
Alors qu'en faisant ceci :
"SELECT * FROM table ORDER BY var1 DESC LIMIT 1"
Tu te retrouve avec... 1 opération.

De plus si ton var1 est un critère régulier de sélection (la plupart de tes requêtes trient avec un test sur var1), met un index sur ce champ. Ainsi la bdd n'aura pas à chercher dans la base, mais regardera seulement sur son "inventaire" smile.gif
Il est possible de mettre plusieurs variables dans un index, pour le cas où tu fais la plupart du temps un test sur ces variables 'WHERE var1='5' AND var2='5'").
Ainsi dans ce que tu dis, si tes var1 et var2 vont par paire, je te conseille vivement un index, index qui ne sera utile qu'à condition que tu utilise les deux variables dans la même requête smile.gif

La première solution est alors de très loin préférable smile.gif


En règle générale, il faut :

- Ne pas oublier les LIMIT
"LIMIT x" pour x enregistrements, "LIMIT x,y" pour les enregistrements entre le xième et le yième.

- Repérer les variables de tri, et leur associer un index à chaque, ou pour plusieurs lorsqu'elles sont utilisées en même temps.

- Mettre un champ id dans toutes les tables !
Ce champ te permettra de lier deux tables par exemple. De plus si tu recherche un joueur ne fais jamais "SELECT * FROM table WHERE nom='pseudo_du_joueur", car tu auras des problème avec tous les caractères spéciaux, et surtout apostrophes et guillemets. Préfère un "SELECT * FROM table WHERE id='id_du_joueur", où l'id n'est qu'un nombre, et met l'id en clé primaire, afin qu'il n'y ait pas deux numéros identiques et que ce soit automatiquement indexé. Tu peux également mettre un auto_increment au champ afin que ton INSERT soit simplifié. Tu n'a alors plus qu'à mettre 0 en id, et la bdd ajoutera la cardinalité actuelle plus 1 pour que ton id soit unique !

- Limiter le nombre de champs dans une table
Ca ne sert à rien d'avoir une table immense regroupant toutes les infos d'un joueurs. Il vaut mieux diviser tes tables en unités logiques, tels que une table pour les données du compte, une pour les données du personnage, une pour les statistiques, etc... Celà allègera pas mal ta bdd wink.gif

- Ne pas être avare en tables
Il vaut mieux ajouter une table avec peu de champs et/ou d'enregistremetns, qu'essayer de caser des données dans une table qui n'est pas faite pour !

- Bien choisir le traitement des données, entre BDD et PHP
C'est bien de vouloir alléger la base de données, mais si celà doit ajouter des calculs en php, ca n'est forcément pas une bonne idée ! Un exemple simple et à éviter, les listes chaînées :
On serait tenté de stocker plusieurs données dans un seul champ en les séparant par un caractère spécial. Des noms de personnes rencontrées par exemple $rencontres="Stabb%YeDo%khiguard%CerberusXL"; Ensuite il suffirait d'exploser la chaine (fonction explode en php) pour obtenir dans un beau tableau avec tous nos noms, un dans chaque case smile.gif C'est une bonne idée à la base, et il est vrai que la base de donnée n'a qu'à renvoyer un champ, et c'est fini... enfin presque. En effet il est extrêmement fastidieux pour un serveur d'exploser de la sorte une chaîne de caractères, et le serveur peut devenir très lent durant ces longues opérations. A la place, il vaut mieux créer une table "personnes_rencontrées", avec en champ l'id du joueur qui rencontre, l'id du joueur rencontré (si on doit avoir accès à des données de ce joueur), le nom du joueur rencontré afin de présenter cette donnée au joueur, et pourquoi pas la date de la rencontre pour trier le tout. On place un index sur la date et l'id du joueur qui rencontre, et on a une table très légère, dont les tris sont très simples, et les résultats très rapides. Le serveur php n'a plus rien à faire qu'à afficher les résultats, et le jeu ne rame pas wink.gif


Il y aurait certainement d'autres choses à dire, mais je crois que là tu pourras éviter les erreurs principales, celles qui augmentent au final le coût d'hébergement de ton jeu !

Enfin, désolé pour le pavé que j'ai mis, j'ai aéré le plus possible, merci pour ceux qui seront arrivé au bout wink.gif


--------------------
PMEmail PosterUsers Website
Top
Haram turval
Ecrit le : Jeudi 13 Octobre 2005 à 07h48
Quote Post


Pro
*

Groupe : Membre
Messages : 126


Je me permet juste de rajouter quelques précisions.

Les index servent non seulement pour les tris mais aussi bien sûr pour les recherches.
Ainsi, un WHERE portant sur un champ indexé donnera de meilleurs temps de réponse.

La commande EXPLAIN de MySQL est très intéressante pour donner des informations sur les index utilisés, les lignes analysées, etc.

Ensuite, il faut choisir bien choisir les champs à indexer et éviter de multiplier les index dans tous les sens. La raison est simple. Chaque index existant sur une table est mis à jours à chaque modification/ajout/suppression dans une table.
Donc, trop d'index sur une table souvent mise à jours peut mettre un serveur à genoux.

Si tu utilises une version de MySQL <= 4, il faut savoir que ce moteur à la sale habitude de bloquer les tables lors des mises à jours. Ainsi, si un joueur fait une grosse mise à jours sur une table, personne d'autre ne peut lire les informations de cette table tant que la requête n'est pas terminée.

Attention également au requêtes avec jointure. MySQL n'est pas réputé pour être efficace dans l'utilisation des JOIN. Du coup, les temps de blocage des tables sont plus long. A cause de ça, j'ai du dire adieu à certains modèles normalisés qui tournaient pourtant sans problème sous d'autre moteurs (SQL Server, PostGreSQL)


--------------------
Tant va la cruche à l'eau qu'à la fin elle est mouillée.
PMEmail Poster
Top
pascaltje
Ecrit le : Jeudi 13 Octobre 2005 à 20h36
Quote Post


Ouf
*

Groupe : Membre
Messages : 242


il faut aussi limiter un maximum le nombre de requetes:
- pas de requetes dans les boucles
- pas de requetes pour reprendre les mêmes infos sur chaque page si ces infos changent peu ou pas du tout (utiliser les sessions)

pour les arborescences, optimiser la lecture par la représentation intervallaire ou l'écriture via une autojointure plus classique.

tu peux / dois aussi limiter la taille de la base en supprimant les infos des joueurs supprimés, limitant les historiques à une certaine durée valable pour comprendre le jeu, limiter le nombre de messages dans les messageries.

A+

Pascal


--------------------
PMEmail PosterUsers Website
Top
Stabbquadd
Ecrit le : Jeudi 13 Octobre 2005 à 21h54
Quote Post


Pro
*

Groupe : Membre
Messages : 76


Une simple précision pour éviter les requêtes dans les boucles.

Le mieux est selon moi de faire un SELECT avant la boucle, afin de ne solliciter le tri qu'une seule fois, d'ajouter bien entendu un LIMIT pour ne pas tout sélectionner. Par exemple dans un classement il vaut mieux faire plusieurs pages, avec une selection uniquement des champs concernés dans cette page, qu'autre chose. Une fois la requête construite, pour parcourir tous les champs, je propose un :
while($enregistrement=mysql_fetch_array($query){ instructions; }

Ainsi toute la sélection sera parcourue, ce qui est parfois inévitable, mais une seule requête sera effectuée, alors qu'à l'inverse, la pire des solutions, ou presque, serait :
for($i=0;$i<=mysql_num_rows($query);$i++wink.gif{
$nom=mysql_result($query,$i,"nom");
$machin=mysql_result($query,$i,"machin");
}
En effet avec une construction de la sorte, à chaque boucle, la bdd doit compter le nombre de champs sélectionné (à cause du test $i<=mysq_num_rows($query)wink.gif, et rechercher l'enregistrement numéro $i autant de fois qu'il y a de données à récupérer... aaaargh wink.gif


--------------------
PMEmail PosterUsers Website
Top
Vanth
  Ecrit le : Jeudi 13 Octobre 2005 à 23h54
Quote Post


Kid
*

Groupe : Membre
Messages : 16


Mecri à tous, je vous aime smile.gif

J'en ai appris encors plus que ce que j'espérai ^^
PMEmail Poster
Top
Vanth
Ecrit le : Vendredi 14 Octobre 2005 à 00h00
Quote Post


Kid
*

Groupe : Membre
Messages : 16


QUOTE (pascaltje @ 13 Oct 2005, 19:36 )
il faut aussi limiter un maximum le nombre de requetes:
- pas de requetes dans les boucles

Arf, ça je m'en doutait...

Je vais devoir changer de méthode pour mon damier ^^

En fait à la base, je lançais la double boucle pour le créer, et à chaque fois je sélectionnais l'image de fond correspondant à la case...

Quelqu'un vois un moyen plus simple pour sélectionner l'image de fond du damier (différentes selon les cases :-/), une idée d'algorythme ?
PMEmail Poster
Top
Stabbquadd
Ecrit le : Vendredi 14 Octobre 2005 à 01h29
Quote Post


Pro
*

Groupe : Membre
Messages : 76


C'est un damier avec des cases noires et blanches ?
Dans ce cas garde une variable booléenne en mémoire, qui alterne entre 0 et 1. 0case noire, 1 case blanche. Ensuite quand tu change de ligne, si ton nombre de case en largeur est pair ( $largeur%2 == true ), alors la première case de la ligne qui commence sera de la même couleur que celle qui vient de se terminer, sinon elle sera de l'autre couleur smile.gif

Ainsi tu n'a qu'à faire une requête pour la première case de toutes wink.gif


--------------------
PMEmail PosterUsers Website
Top
[VYS]
Ecrit le : Vendredi 14 Octobre 2005 à 09h35
Quote Post


Ouf
*

Groupe : Membre
Messages : 317


QUOTE (Vanth @ 14 Oct 2005, 00:00 )
QUOTE (pascaltje @ 13 Oct 2005, 19:36 )
il faut aussi limiter un maximum le nombre de requetes:
- pas de requetes dans les boucles

Arf, ça je m'en doutait...

très souvent un problème de requetes "imbriquées" dans une boucle peut être réglé grace à une simple jointure de type LEFT JOIN

à la place de
CODE
Requete1 = "SELECT * FROM MaTable1"
While(Elements de Requete1)
{
   Requete2 = "SELECT * FROM MaTable2 WHERE ID_FK=".$InfoTable1
}


Il faut utiliser
CODE
Requete = "SELECT * FROM MaTable1 LEFT JOIN MaTable2 ON MaTable2.ID_FK = MaTable1.Info"


--------------------
VYS - DungeonMaster
* président asbl JeuxWeb.org
* webmaster MountyHall - La Terre des Trõlls
user posted image
PMEmail PosterUsers Website
Top
Stabbquadd
Ecrit le : Vendredi 14 Octobre 2005 à 10h09
Quote Post


Pro
*

Groupe : Membre
Messages : 76


Merci [VYS], tu m'a appris quelque chose au passage wink.gif
J'avoue que j'en ai pas encore eu l'utilité, ou alors ca m'a échappé tongue.gif , mais que ca me permettra certainement d'envisager de nouvelles choses, ou au moins de nouvelles manières de les aborder smile.gif
(ah oui, si vous aviez pas remarquer, j'adore apprendre wub.gif )


--------------------
PMEmail PosterUsers Website
Top
Vanth
Ecrit le : Vendredi 14 Octobre 2005 à 12h15
Quote Post


Kid
*

Groupe : Membre
Messages : 16


QUOTE (Stabbquadd @ 14 Oct 2005, 00:29 )
C'est un damier avec des cases noires et blanches ?
Dans ce cas garde une variable booléenne en mémoire, qui alterne entre 0 et 1. 0case noire, 1 case blanche. Ensuite quand tu change de ligne, si ton nombre de case en largeur est pair ( $largeur%2 == true ), alors la première case de la ligne qui commence sera de la même couleur que celle qui vient de se terminer, sinon elle sera de l'autre couleur smile.gif

Ainsi tu n'a qu'à faire une requête pour la première case de toutes wink.gif

non non, ça aurait été beaucoup trop simple ^^

Il ya a beaucoup d'images différentes dedans, par damier, je veux dire tableau x case y colonnes, c'est tout^^

Le Damier en question ressembleara à beucoup de jeu php façon démange.

EDIT : Merci Vys, je ne sis pas si ça va arranger mon pb, mais je commence à avoir quelsques pistes de réflexion
PMEmail Poster
Top
[VYS]
Ecrit le : Vendredi 14 Octobre 2005 à 12h23
Quote Post


Ouf
*

Groupe : Membre
Messages : 317


si tu veux m'envoyer (par mail : dm@mountyhall.com) ton script (la requete principale, la boucle et les requetes inbriquées) et la structure des yables impactées, je te corrigerais ca en jointure et le publierais ici si tu acceptes de partager l'info.


--------------------
VYS - DungeonMaster
* président asbl JeuxWeb.org
* webmaster MountyHall - La Terre des Trõlls
user posted image
PMEmail PosterUsers Website
Top
Stabbquadd
Ecrit le : Vendredi 14 Octobre 2005 à 19h47
Quote Post


Pro
*

Groupe : Membre
Messages : 76


Personnellement ca m'intéresse, un petit exemple smile.gif
A la limite fait un petit rechercher remplacer sur les noms des tables et de champs, c'est toujours mieux de ne pas publier ces noms, ca limite les exploits en passant par un champ de formulaire qu'on aurait mal sécurisé ^^


--------------------
PMEmail PosterUsers Website
Top
Vanth
Ecrit le : Vendredi 14 Octobre 2005 à 23h56
Quote Post


Kid
*

Groupe : Membre
Messages : 16


QUOTE ([VYS] @ 14 Oct 2005, 11:23 )
si tu veux m'envoyer (par mail : dm@mountyhall.com) ton script (la requete principale, la boucle et les requetes inbriquées) et la structure des yables impactées, je te corrigerais ca en jointure et le publierais ici si tu acceptes de partager l'info.

Ok, dès que je trouve le temps je te balance le code version simpifiée comme tu le demandes wink.gif
PMEmail Poster
Top
« Sujets + anciens | Hébergement et services | Sujets + récents »

Reply to this topicStart new topicStart Poll