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

> Comment Optimiser Ma Table Sql ?, Si je n'ai pas de clé unique
la_couenne
  Ecrit le : Mardi 16 Avril 2013 à 19h16
Quote Post


Newbie
*

Groupe : Membre
Messages : 9


Bonjour à tous!

Voilà, cela fait + d'un an que je suis sur le développement de mon jeu web, ça commence à donner quelque chose de pas trop mal.
Seulement avant avec une trentaine de joueurs sur ma petite carte, ma page s'affichait en 2 secondes, maintenant j'ai agrandi la carte de jeu et du coup avec un seul perso dessus, elle met jusqu'à 5 sec pour s'afficher! je vais devoir sérieusement apprendre à optimiser mes bases de données..

Voici mon problème, j'ai 100 cartes, qui contiennent chaqune 40x40 cases. J'affiche une carte à la fois, celle ou se trouve le joueur.
Ma table s'appelle "world" et a 4 colonnes (je simplifie un peu, mais le principe est là..)
------------------------------------------
| world |
------------------------------------------
| carte | case | contenu | id_joueur
| 100 | 1010 | ici il y a le contenu la case 1010 de la carte 100
| 100 | 1110 | et là le contenu la case 1110 toujours sur la carte 100
...
| 101 | 1010 | ici c'est une autre carte (la 101) donc "case" ne peut pas être primaire puisque 1010 existe dans la carte 100..

Ma question est: comment indexer si je n'ai pas de clé primaire? (des contenus pas unique puisque les cases 1010 seront sur plusieurs carte)
est-ce que KEY `carte` (`carte`,`case`); est correct?

J'ai donc créé donc mon index, seulement maintenant j'ai un problème d'affichage des cases: elles n'apparaissent plus dans l'ordre:
Avant avec ma table sans index et en exécutant ma requête:
SELECT `case` FROM `world` WHERE `carte`='100'
il me retournait:
1010
1110 (soit les coordonnées de ma case X:11 et Y:10)
1210
1310
1410
...

et maintenant que j'indexe ma table en ajoutant:
KEY `cluster` (`cluster`,`case`) lors de sa création
ma requête:
SELECT `case` FROM `world` WHERE `carte`='100'
me retourne:
1010
1011 (soit les coordonnées de ma case X:10 et Y:11)
1012
1013
1014
...

seulement c'est un énorme problème, car je suis obligé de faire apparaître mes cases dans le bon ordre, afin de les afficher par coordonnées X-Y!
Donc ma carte de 40x40 cases se présente:
1010 1110 1210 1310 ...
1011 1111 1211 1311 ...
1012 1112 1212 1312 ...
...

J'ai essayé de mettre:
SELECT `case` FROM `world` WHERE `carte`='100' ORDER BY `case` ASC mais évidement c'est pas ça (ca m'affiche 1010 1011 ...)

j'ai solutionné mon problème en faisant tout bêtement une boucle pour l'affichage de chaque ligne:
$Y=10;
debut:
$reponse = mysql_query("SELECT `case` FROM `world`
WHERE `carte`='100' AND `case` like '%".$Y."' ORDER BY `case` ASC"); //ça affiche toutes les cases pour $Y (donc par ligne)
while ($donnees = mysql_fetch_array($reponse)){
echo $donnees['case'].'<br/>';}
if ($Y<40){$Y++; goto debut;}
Mais ca me fait pour afficher une carte: 40 requêtes pour mes 40 lignes Y, c'est pas le top de l'optimisation ça..

Donc si mon problème parle à quelqu'un, je serais très intéressé wink.gif
Bonne fin d'semaine à tous..
PM
Top
Cedric
Ecrit le : Samedi 18 Mai 2013 à 01h56
Quote Post


Ouf
*

Groupe : Membre
Messages : 368


Je n'avais pas vu ton message... mais le probleme que tu as est que fondamentalement il te faudrait decomposer ton numero de case en 2.
1011 => X = 10 / Y = 11
Apres il te sera tres facile de tout ordonner.

Je te conseille sinon :
- de creer une clef primaire auto increment
- de creer un index sur ton monde
- de creer un index sur X
- de creer un index sur Y
... vu comment tu comptes y acceder.


--------------------
user posted image
PMEmail PosterUsers Website
Top
la_couenne
Ecrit le : Mercredi 22 Mai 2013 à 10h27
Quote Post


Newbie
*

Groupe : Membre
Messages : 9


Merci bcp pour ta réponse!

J'avais bien pensé séparer en deux mes numéros de cases, mais à ce moment je dois changer tout mon code, et ca ne me tente vraiment pas! en tout cas pas pour le moment..

Ca fait 1 an que je suis sur le développement de mon jeu, pour le moment je le teste comme ca en local, ce qu'il y a c'est que pour le faire tourner mon serveur fait tourner un cron toute les 10 secondes, alors qu'une fois hébergé les crons on peut les faire se lancer au minimum 1x toutes les 15min..

Mon jeu est un peu "spécial", en fait les joueurs définissent le génome de petites bébêtes, qui vont s'adapter à leur environnement et se reproduire. Si le joueur veut conquérir un endroit précis du monde, ses bestioles devront savoir s'adapter à chaque partie du monde pour atteindre l'endroit visé..

Ca paraît compliqué dit comme ca, mais c'est intéressant comme jeu, mon problème c'est que ce n'est pas tellement les joueurs qui déclenchent des actions, c'est le serveur qui fait se déplacer leur bestioles, donc quand il y en a 100 ca marche, mais quand il y en a 1'000 il est obligé de les mettre à jour toutes les 10 ou 15 secondes sad.gif

Bref j'y travaille et on verra ce qu'il en ressort.. et une fois je pourrais aussi présenter l'idée de mon jeu voir ce que vous en dites, mais j'aimerais pas en parler pour abandonner 3 mois après...

Merci encore pour ta réponse! A tout bientôt smile.gif

Ce message a été modifié par la_couenne le Mercredi 22 Mai 2013 à 10h29
PM
Top
Oelita
Ecrit le : Mercredi 22 Mai 2013 à 11h58
Quote Post


Alien
*

Groupe : Admin
Messages : 1591


Evite les select LIKE de toutes façons, et encore moins 40 à la suite.
Fais un unique select de toutes les cases de ton monde, puis travaille sur le tableau des résultats (une boucle sur toutes lignes du tableau) pour ajouter les deux colonnes X et Y au tableau (ou en faire un autre), à partir du numéro de la case. Après, tu tries le tableau sur la colonne Y (fonction PHP) et c'est bon. Le travail sur le tableau en PHP prendra moins de temps que tes 40 requêtes avec LIKE.

Après réflexion, tu peux aussi récupérer directement ta valeur Y dans ton select en faisant un calcul modulo 100 du numéro de la case (j'ai pas essayé mais ça devrait fonctionner ) :

select case, MOD(case, 100) as Y, donnees FROM world
WHERE carte=100 ORDER BY Y ASC, case ASC


--------------------
Oëlita la Gentille Hérétique
Admin TourDeJeu
user posted image

Le moyen le plus efficace pour me contacter ? @Oelita sur Twitter
PMEmail PosterUsers Website
Top
la_couenne
Ecrit le : Dimanche 26 Mai 2013 à 20h12
Quote Post


Newbie
*

Groupe : Membre
Messages : 9


Merci de ta réponse! j'ai pas répondu tout de suite car j'ai pas eu le temps de m'y pencher, mais ça me semble être une bonne idée, c'est vrai que je n'ai pas pensé travailler sur un tableau!

Dès que j'ai un peu de temps, je vais m'y repencher, comme pour l'instant je travaille en local j'ai pas de problème, mais je serais obligé d'y régler assez vite. Je te tiendrai au courant de ce que j'arrive à pondre smile.gif
PM
Top
Gwym
Ecrit le : Mardi 28 Mai 2013 à 20h53
Quote Post


Kid
*

Groupe : Membre
Messages : 17


Une solution serait plutôt que de coder "case" en caractères (i.e. comme présenté, deux digits pour x deux digit pour y), mettre case en valeur numérique pure "numéro de la case" allant de 0 a 40*40

carte case
1 1
1 2
1 ...
1 1600
2 1
etc
et récupérer les coordonnées
select case, ... FROM world WHERE carte= n
puis extraire au niveau du code (ou directement dans le sql)
x = (int) (case / 40)
y = case % 40

Par contre pourquoi ne pas simplement vraiment faire trois colonnes ?

carte | x | y

car au moindre changement de structure (exemple tu décides de faire des cartes de 50 par 30)
il faudra faire des changements dans le code, alors qu'un
SELECT x, y FROM world WHERE carte = n
sera toujours valide
PMEmail PosterUsers Website
Top
« Sujets + anciens | Programmer | Sujets + récents »

Reply to this topicStart new topicStart Poll