Forum TourDeJeu · Règles du forum | Aide Recherche Membres |
Bienvenue invité ( Connexion | Inscription ) | Recevoir à nouveau l'email de validation |
manakeo |
Ecrit le : Dimanche 15 Octobre 2006 à 15h54
|
Pro Groupe : Membre Messages : 119 |
Bonjour à tous les programmeurs,
J'aurais une petite question au niveau organisation du code. Est-il préférable d'avoir différentes tables du style: tableNourriture / tableBoisson / tableMatiere / tableVetement / tableObjet ou alors une seule table : tableCOmplete Alors les deux ont des avantages et des inconvenients, j'arrive pas à me décider. Par exemple dans son inventaire, pour afficher la liste des objets que l'on possède, il faudra faire une requete select dans chaque table, alors qu'avec une seul, une requete suffit. si certain programmeurs ont une méthodes préférables, ou meme un autre... voilou -------------------- |
Dal'Yth |
Ecrit le : Dimanche 15 Octobre 2006 à 17h19
|
Newbie Groupe : Membre Messages : 7 |
A première vue :
Je pense que les objets doivent être mis à part car ils ne sont pas tout le temps sur un joueur, ils peuvent être au sol, dans une maison, ... Par contre des trucs comme boissons et nourritures tu pourrais peut être les regrouper. Mais je ne connais pas ton jeu, donc je te conseille : - de voir quand tu appelle ces tables - comment et en quelle quantité (=> critères de sélection) - quels vont être les critères de sélection : si tu appelle souvent les objets et les vêtements en fonction de la personne qui les porte, il vaut mieux une table commune. Par contre si tu affiche plus souvent les objets en fonction de leur position, une table séparée objet est plus pratique. Réfléchi aussi au champ index que tu vas utiliser, ça peut t'aider à choisir. Cela dit, c'est vrai qu'il n'y a pas de solution parfaite, comme tu l'a remarqué il y a des avantages et des inconvénients à chaque solution, il faut pourtant choisir. J'espère avoir pu t'aider un peu |
nygma |
Ecrit le : Dimanche 15 Octobre 2006 à 21h24
|
Pro Groupe : Membre Messages : 129 |
perso, j'ai mis tous les objets dans une seule table.
chaque objet appartient à une famille d'objet. chaque famille d'objet possède une instance spécifique dans des tables plus 'spécialisées'... (armes, sortilèges liés, lumières, etc...) les objets pouvant être au sol, sur des persos, ou dans un autre objet etc... j'ai des tables de jointure pour les suivre. franchement, je te conseille de regrouper tout ce qui a un traitement commun. Y'a rien de pire que de faire du code en double. |
Vantik |
Ecrit le : Dimanche 15 Octobre 2006 à 22h45
|
Kid Groupe : Membre Messages : 44 |
Idem je pense que tout mettre dans la même table et d'ensuite faire des jointures serait le plus pratique.
Maintenant ça peux dépendre de ce que tu veux faire précisement, mais à mon avis dans la majorité des cas, une table unique est préférable. A toi de voir . |
manakeo |
Ecrit le : Dimanche 15 Octobre 2006 à 22h56
|
Pro Groupe : Membre Messages : 119 |
Merci pour vos réponse.
Le problème est qu'au bout de plusieurs milliers d'objet, la table sera lourde. ^^ Ce qui me fait douter est d'un point de vue "attribut". Chaque type d'objet a ses attributs comme: poids / attaque / defense / luminosité etc etc. Pour la pluspart des objets, ces attributs n'intervienne pas. Bref, je pense donc rester sur la facon dont tout a été organisé, c'est a dire avec une seule table. J'espère ne pas a avoir a changer -------------------- |
Grouik |
Ecrit le : Lundi 16 Octobre 2006 à 01h11
|
||
Kid Groupe : Membre Messages : 27 |
Salut, J'imagine que tu utilises une base de données relationnelle (MySQL ?). L'avantage du relationnel, contrairement aux bases de données de l'ancien temps, est de ne pas être obligé de tout stocker dans une seule table. Le principe étant de substituer à une grosse table unique plusieurs tables reliées entre elles par des relations définies (d'où le nom de ce type de bases). Gain de structuration, gain de temps de requêtage... le seul point où l'on y perd est sur la compléxité des requêtes (encore que ce soit relatif, on a vu plus compliqué que le SQL). Bref, je dirais : 1. si tu maîtrises suffisamment le SQL, ton choix devrait se porter sur plusieurs tables ; 2. si tu es une grosse quiche en SQL, ton choix devrait se porter sur une seule table (comme faisait papy en son temps) ou d'apprendre un minimum de SQL et d'opter pour l'option 1. Celà dit, il ne faut pas être dogmatique et d'autres raisons que je ne connais pas (contraintes hébergeur, volumétrie attendue, compétence de co-développeurs, ...) impliquent peut-être le choix 2. Remarque complémentaire sur la structuration en plusieurs tables : Imaginons que tu ais à stocker des objets dont de la nourriture, des objets manufacturés incluants des armes et des vêtements. Toutes tes tables ne seraient pas au même niveau mais reprensenterais plutôt un arbre. OBJET (id_objet, volume, poids) NOURRITURE (id_nourriture, id_objet, duree_conservation, valeur_nutritive) OBJET_MANUFACTURE (id_objet_manufacture, id_objet, nom_fabriquant, date_fabrication) ARME (id_arme, id_objet_manufacture, resistance, degats) VETEMENT (id_vetement, id_objet_manufacture, sexe, taille) Ainsi, pour connaître le poids de l'arme d'identifiant 42, la requête aurait la forme suivante :
En bonus, c'est conceptuellement plus facile à mapper si tu utilises un langage orienté objet pour ton site. My 2 cents... -------------------- "Personnellement, c'est pas Dieu qui me dérange, c'est son putain de fan club..."
|
||
Sybler |
Ecrit le : Lundi 16 Octobre 2006 à 04h58
|
Ouf Groupe : Membre Messages : 453 |
J'ai aussi opté pour placer tout les objet dans une même table, et ce après avoir au préalable essayé réellement une structure séparée pour chaque type d'item.
Grosse table d'item: - Permet de créer des items hybrides - Évite de faire 15 requêtes pour lister un inventaire Table multiples - Fait plus jolie dans des graphique de modélisation, mais en pratique c'est très bof (enfin, dans mon cas ca donné un truc très bof) Structure approximative de ma mega table: id type [arme, drogue, etc] soustype [arme_feu, arme_blanche, drogue_pillule, drogue_injecte, etc] perso_id (null= appartiend à aucun perso) lieu_id (null= appartiend à aucun lieu) ..... Le champs Type, perso_id et lieu_id sont en index, et ID en primary, ce qui permet de faire des recherches rapides. A NOTER QUE MYSQL EXÉCUTE LES "WHERE" DE DROITE À GAUCHE. Donc une requete comme celle-ci sera très rapide: SELECT * FROM table WHERE type='drogue' AND perso_id=108; Et celle-ci, très lente: SELECT * FROM table WHERE perso_id=108 AND type='drogue'; Vu que la denière doit sélectionner TOUS les items drogues du jeu pour ensuite recherher uniquement les 2-3 du personnage. ============================================= Edit: Question personnelle pour Mr. "Quand t'es bon en SQL tu fais 6 millions de tables" Si chaque item à une table de base, et une table de 'personnalisation': Base+Personnalisation=1 item personnalisé dont la base reste gérable en masse en un seul point de contrôle. Donc, déjà la, c'est 2 tables. Maintenant j'ai 25 types d'items. Je fais 50 tables ?, Soit 25 requêtes à jointure pour afficher la liste d'un inventaire ?! Continuons l'excercice... L'item peut-être possédé par un personnage, un lieu, ou une boutique... Surement qu'on devrait aussi segmenter alors, vu que MySQL est relationnel et si puissant. 50x3 = 150 tables cool, maintenant explique moi comment ca sera pas vraiment plus chiant à programmer ... et surtout j'aimerais bien avoir un exemple de requête de jointure monstre qui va relier 150 tables pour adopter un shéma de ... hum... ouais, quatrième dimension ! Edit2: Ca sonne peut-être méchand, mais ca l'est pas dutout -------------------- |
nygma |
Ecrit le : Lundi 16 Octobre 2006 à 07h57
|
Pro Groupe : Membre Messages : 129 |
il ne faut pas faire un table par type d'item.
il faut faire une table de types d'item. en tout et pour tout, j'ai une vingatine de tables pour gérer les objets. (nota, je ne gère pas les liquides) pour le détail, voir ici : Modèle de donnée. C'est pas la toute dernière version, mais ça donne les grandes lignes. Les tables importantes sont : * base_type_objets_main items_objets_main base_types_objets_sorts_main items_objets_pieces items_objets_armes items_objets_armures items_ouvertures .... A noter, pour certains objets TRES spécifique, il faut mieux faire des tables à part. [edit] précision : quand je dis à part, c'est en plus de la table commune.[/edit] (les clés, les armes, ....) |
the-gtm |
Ecrit le : Lundi 16 Octobre 2006 à 08h10
|
||
Pro Groupe : Membre Messages : 130 |
D'accord avec le principe de mettre tous les items dans une même table. Par contre :
C'était peut être vrai sur les toutes premières versions mais ça fait longtemps que l'optimiseur de requêtes arrive à gérer ce genre de cas. En tout cas sur MySQL 4 il fait les deux requêtes de la même manière. |
||
manakeo |
Ecrit le : Lundi 16 Octobre 2006 à 19h10
|
||
Pro Groupe : Membre Messages : 119 |
C'est exactement ce à quoi je pensais. J'ai uncertain niveau en anlayse, merise UML etc, mais il est vrai que la théorie et la pratique... des fois cè relou. Il est évident que pour avoir un truc propre, clair, il faut séparer. Le soucis étant que mysl a du mal avec l'héritage. Ce qui provient de ce système de donnée. Objet => classe mère le reste: héritage de la classe objet. AVec un code orientée objet, cela peut passer je pense, mais bonjour les requetes. De plus a chaque fois que tu ajoutes une tables, donc un type d'objet, tu dois modifier toutes tes requetes? A mois de gerer ca en objet -------------------- |
||
Oelita |
Ecrit le : Lundi 16 Octobre 2006 à 22h57
|
Alien Groupe : Admin Messages : 1589 |
A un moment ou à un autre, il faudra bien distinguer le traitement de ces objets... Si vous mettez tout dans une seule table, vous aurez des propriétés vides, par exemple un objet de nourriture n'a pas de propriété de dégâts. Donc même si vous faite un seul SELECT tout simple pour l'inventaire, va falloir tout séparer ensuite au niveau traitement pour ne pas afficher de propriété dégâts pour la nourriture, non ? donc ça me parait un peu artificiel de tout vouloir regrouper pour "simplifier".
Pis si vous rajoutez une propriété sur un type d'objet, faudra modifier tout le code pour tous les objets ? Bref, ya du pour et du contre dans les deux cas. Sur TdJ, j'avais regroupé certains trucs car ils avaient pas mal de propriétés communes (en l'occurrence, j'avais regroupé : les news, les annonces, les commentaires de focus, les commentaires de jeux)... et j'ai fini par les séparer plus tard, car marre de gérer les filtres sur les champs de "type" pour toutes les requêtes non communes. Pis ça alourdissait aussi les temps de réponse. Bref, sur la page du MJ qui regroupe les infos de son jeu (l'équivalent de l'inventaire, donc), j'ai donc maintenant 3 requêtes distinctes pour récupérer les news passées, les annonces passées et les derniers commentaires, au lieu d'une seule, mais au niveau code PHP c'est beaucoup + clair, je trouve. -------------------- |
Sybler |
Ecrit le : Mercredi 18 Octobre 2006 à 03h31
|
||||
Ouf Groupe : Membre Messages : 453 |
Article d'Avril 2006: http://www.dublish.com/articles/10.html Tu as quelque chose d'officiel pour appuyer tes dires (pas que je ne te fasse pas confiance, mais j'aimerais voir ca d'écrit dans une documentation plus sérieuse) -------------------- |
||||
Haram turval |
Ecrit le : Mercredi 18 Octobre 2006 à 10h43
|
Pro Groupe : Membre Messages : 126 |
J'ai fait des tests et il semble se confirmer que MySQL execute les WHERE de droite à gauche
En prenant une table existante de 2000 lignes et en faisant un WHERE composé de deux éléments (un champ indexé et l'autre non ), il y a des différences de temps de traitement en fonction de la position du champ indexé dans le where. Le temps de traitement est 10-20% plus rapide en mettant d'abord le champ indexé puis le champ non indexé dans le WHERE. Testé sur MySQL - 4.1.11 -------------------- Tant va la cruche à l'eau qu'à la fin elle est mouillée.
|
the-gtm |
Ecrit le : Mercredi 18 Octobre 2006 à 20h27
|
Pro Groupe : Membre Messages : 130 |
Je me base sur le plan des requêtes (EXPLAIN) qui indique quels sont les index utilisés.
J'ai fait un test sur MySQL 4.1.10, sur une table de 2000+ lignes, avec une requête portant sur un champs indexé, un pas indexé (la requête ramène 100 lignes) : 10 000 requêtes pour initialiser le bidule 10 000 avec le champs indexé en 1er 10 000 avec le champs indexé en 2e J'obtiens un temps environ 1% inférieur en mettant le champs indexé en fin de requête. Etant donné que le plan des deux requêtes est le même (utiliser l'index), la différence vient pour moi du temps pris par l'optimiseur pour calculer ce plan. Bref pas de quoi casser trois pattes à un canard mais ça ne fait pas de mal de mettre le champs indexé à la fin. |
Haram turval |
Ecrit le : Mercredi 18 Octobre 2006 à 22h21
|
Pro Groupe : Membre Messages : 126 |
Attention lors des tests, le cache peut fausser les résultats si les requêtes sont lancées en boucle les une après les autres.
Dans mon cas, en lançant les requêtes en boucle, la différence devient négligible avec le nombre car seule la première exécution montre un écart. Il est recommandé de changer les paramètres de requête à chaque exécution pour éviter d'avoir des résultats faussés par le cache. -------------------- Tant va la cruche à l'eau qu'à la fin elle est mouillée.
|
Haiken |
Ecrit le : Mercredi 18 Octobre 2006 à 22h56
|
Ouf Groupe : Membre Messages : 360 |
... ou de demander explicitement à ne pas mettre la requête en cache : "SELECT SQL_NO_CACHE id, name FROM customer"
-------------------- Association Nainwak, aide & hébergement des jeux web
Le Blog de l'assoc', encore mieux que l'assoc' tomate ! |
the-gtm |
Ecrit le : Jeudi 19 Octobre 2006 à 08h12
|
Pro Groupe : Membre Messages : 130 |
J'ai rajouté SQL_NO_CACHE et j'ai fait varier les paramêtres de la requête, cette fois les résultats sont inversés : c'est un peu moins de 1% plus rapide en mettant le champs indexé en 1er... Bref les deux donnent le même résultat
Le problème en ne jouant la requête qu'une fois c'est que tu comptes le temps mis par la base pour compiler et optimiser la requête. Ce temps n'est pris qu'une fois parce que la base mets en cache le plan des requêtes (je ne parle pas des résultats ici). En plus quand tu as une requête qui dure quelques millisecondes, une imprécision de +/- 1ms est très importante. En pratique, c'est difficle d'avoir un résultat fiable sur une seule requête. Globalement ce que voulait surtout dire c'est que la base optimise les requêtes pour utiliser les index au maximum. Si la clause where comprend un champs indexé c'est presque certain que l'index sera pris. S'il y en a plusieurs ça se complique ... Pour ceux qui veulent des précisions : la doc mysql |
Haiken |
Ecrit le : Jeudi 19 Octobre 2006 à 22h18
|
Ouf Groupe : Membre Messages : 360 |
oui attention quand même, si je ne m'abuse le plan de requêtes n'est conservé qu'avec les requêtes préparées.
Attention aussi, les requêtes préparées ne sont jamais conservées dans le cache de requêtes (ce qui est fort dommage) donc à n'utiliser qu'avec d'infinies précautions. Détails ici (ça concerne mysqli, et aussi PDO sauf dans les toutes dernières version de PHP) -------------------- Association Nainwak, aide & hébergement des jeux web
Le Blog de l'assoc', encore mieux que l'assoc' tomate ! |