[Résolu] Comment stockez-vous vos quantités de ressources ? - Version imprimable +- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org) +-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38) +--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51) +--- Sujet : [Résolu] Comment stockez-vous vos quantités de ressources ? (/showthread.php?tid=7103) Pages :
1
2
|
[Résolu] Comment stockez-vous vos quantités de ressources ? - Sephi-Chan - 11-08-2013 Bonjour, J'avance bien sur Seelies ces derniers temps et une question s'est récemment posée : la façon dont stocker une quantité de ressources. J'ai plusieurs types de ressources (environ une dizaine), disons pour l'exemple : l'herbe, les feuilles, le bois et la pierre. Et j'ai de nombreux usages de ces ressources :
Mine de rien, ça fait pas mal d'usage (et j'en ai potentiellement d'autres qui ne sont pas encore définitifs) et il y a plus d'une façon de stocker ça. Un système très souple mais un peu complexe L'idée serait d'utiliser une table de relation (resource_type_thing), qui associe une quantité d'un type de ressource à n'importe quoi (un convoi, un type de bête, c'est polymorphe). Pour ça, 5 colonnes :
Au niveau de mes tables :
Un système simple mais rigide L'autre approche est de stocker dans chaque table une colonne pour chaque ressource et chaque usage. Si j'ajoute une ressource dans le jeu, c'est un peu chiant. Ainsi, dans ma table beast_types (qui a plusieurs usages), j'aurais des colonnes consumption_resource_type_1_quantity , consumption_resource_type_2_quantity , harvesting_resource_type_1_quantity .Un système simple et flexible Une autre approche consiste à stocker dans une colonne dédié du contenu sérialisé (via le type JSON ou Hash de PostgreSQL). Ainsi, dans la colonne resources de ma table beast_types (toujours avec ses usages mulitples), j'aurais quelque chose comme :
Voilà, qu'en pensez-vous ?
Dans les 3 cas mon API côté application sera la même. Donc je n'ai qu'à prendre la meilleure pour mon cas. RE: Comment stockez-vous vos quantités de ressources ? - Xenos - 11-08-2013 Salut, sérialiser les données dans une BDD m'a toujours un peu fait pleurer... C'est un peu comme certains concepteurs que j'ai connu, qui étaient ravis d'avoir une base de données avec 2 tables: 1 qui contient absolument n'importe quel objet (sérialisé) et une qui contient les liens entre ces objets. Bon, ben à ce compte là, autant ne pas utiliser de SGDB et faire deux fichiers binaires sur son FTP. La problématique production / consommation / stockage peut se développer comme un système d'équations mathématiques. Si tu sérialises, tu auras énormément de difficulté à envoyer ces équations au SGDB, puisqu'il faudra d'abord récupérer les données, puis les désérialiser, puis les traiter (souvent, on utilise alors non pas une solution exacte mais une approximation type Euler avec un intervalle de temps dT par exemple), puis les resérialiser, et enfin les remettre dans la BDD... C'est d'un lourd et d'un long ! J'hésiterai plutôt entre la solution souple, mais couteuse ou la solution rigide mais légère et simple. Ayant des mutualisés limités en terme de place pour la BDD, j'utilise plutôt la solution rigide légère. L'ajout d'une ressource change énormément le gameplay, et donc, on n'ajoute pas des ressources "à la volée", toutes les 30 secondes. Le fait que ce soit un peu chiant n'est pas vraiment un problème (si c'était impossible, ce serait différent). Si t'as une place illimité, je dirai que le choix entre souple ou rigide dépendra de la fréquence d'ajout de ressources que tu comptes avoir. Si tu comptes laisser l'ajout de ressources possibles "juste au cas où", j'opterai pour la rigide simple. Si l'ajout de ressources est prévu et régulier, j'utiliserai la souple lourde. Dans aucun des deux cas je ne me tournerai vers les sérialisés. J'ajouterai d'ailleurs que niveau place, les données sérialisés sont très couteuses (il me semble), puisque ce sont des chaînes de caractères. Ah, aussi, le système simple dépend de la densité de chaque ligne: si tu as 20 ressources différentes (donc, 20 colonnes si j'ai bien suivit), et que chaque unité n'a généralement qu'une ressource ou deux, alors 18 colonnes seront à "0", ce qui peut faire beaucoup de données inutiles. En ce cas, la solution souple mais "lourde" sera finalement plus légère. RE: Comment stockez-vous vos quantités de ressources ? - Sephi-Chan - 11-08-2013 Bien sûr, l'usage abusif de sérialisation est à proscrire. Celui que je décris — qui utilise un mécanisme de la base de données (le type hstore de PostgreSQL, transparent à l'utilisation) est plutôt sain. L'application sera hébergée sur du dédié, je peux me lâcher sur le stockage. Par ailleurs, je ne compte pas avoir des tonnes de ressources (la dizaine que j'évoque me semble un bon maximum), et je doute en rajouter souvent par la suite. Je n'utiliserais les ressources que pour des résolutions ponctuelles, notamment à chaque changement d'heure. Puis par plus petites touches pour de l'affichage. Je ne sais pas à quel point ce que tu décris concernant les équations mathématique me concerne (ce n'est vraiment pas un milieu dans lequel je suis à l'aise). La densité des informations sera assez importante puisque la plupart des bêtes peuvent toucher un peu à tout. Donc je pense qu'il n'y aura peu de gâchis. Après renseignement, les NULL ne coûtent presque rien dans PostgreSQL (gratuit pour une table jusqu'à 8 colonnes, puis 8 octets par tranche de 64 colonnes). Le stockage étant bon marché, il est plus intéressant de favoriser des colonnes NULL que des jointures. D'ailleurs, pour ceux que ça intéresse, voici le lien vers le coût des NULL dans MySQL. Le fonctionnement des tables InnoDB (utilisé par défaut depuis MySQL 5.5) se rapproche de PostgreSQL (les NULL ne coûtent presque rien). C'est plus coûteux avec MyISAM. Merci Xenos pour tes réponses : c'est analytique, c'est sympa. RE: Comment stockez-vous vos quantités de ressources ? - Xenos - 11-08-2013 Ok, hstore semble mieux que la bête chaine de caractères, mais je pense que la sérialisation (quelle que soit la dose) a un mauvais point: la structure (id des ressources) est stockée dans les données, et je pense qu'avec ce genre d'approche, il devient facile de s'emmêler les pinceaux. Le NULL est couteux pour MyISAM mais ce dernier présente l'avantage (de mémoire) d'avoir des lignes de longueur fixe (tant qu'on n'utilise que des types entiers / flottants et non des chaines de caractères de longueure variable). C'est pratique en cas de crash, et cela speed un peu plus pour les requêtes. Et donc, oui dans ce cas là avec NULL qui coute des cacahouètes, la structure rigide sera plus attrayante (tant pour les perfs que la maintenance) que la structure à jointures, surtout au niveau des index. Si jamais les tables font des kilomètres de long avec un nombre de colonnes déprimant, tu pourras toujours les scinder en deux. RE: Comment stockez-vous vos quantités de ressources ? - Maks - 11-08-2013 Si tu cherches quelque chose de souple, pense au NoSQL. Si ça t'ennuies d'avoir deux bases de données, avec Postgres et les hstore ça avait l'air cool dans le Railscast. Perso, j'ai une base de donnée relationnelle assez conventionnelle pour les données qui s'y prêtent bien (gestions des membres, des news, du forum...) et Mongo pour les données de jeu qui nécessitent pas mal de ressources imbriquées. Le tout c'est d'avoir un bon ODM pour que ça soit pas le bordel (Mongoose peut gérer des jointures par exemple). RE: Comment stockez-vous vos quantités de ressources ? - niahoo - 11-08-2013 Si tu veux jouer sur le faible coût des NULL ça serait pour la solution 2 si j'ai bien suivi, hein ? Si j'ai bien suivi aussi (car j'avoue avoir un peu de mal ce "matin") tu veux stocker ces infos pour les types de bestioles nan ? Pas pour chaque bestiole appartenant à chaque joueur. Donc, tu peux pas tout simplement faire un gros JSON pour la persistance mais surtout le charger en RAM au démarrage du serveur ? Ou même générer un fichier de code source ? car c'est le genre d'infos auxquelles on fait référence tout le temps et qui ne pèsent pas bien lourd en RAM. Bon et si c'est bestiole par bestiole ben du coup vu que ton API est déjà fixée, tu peux switcher entre différentes solutions sans casse. Donc je prendrais la plus simple à implémenter, la 3 il me semble. Un article intéressant qui décrit le modèle de données du CMS le plus rapide au monde, basé sur PostgreSQL avec, notamment, des genre de hash, mais pas que : http://zotonic.com/documentation/670/data-model-erd (en fait les hash de données ne sont pas des hash postgresql, ils sont stockés dans un champ binaire (donc grosse sérialisation mais hyper rapide) et servent de référence, ensuite un cache avec de vraies colonnes est construit à partir de cette référence, et là on se rapproche plus de ta première solution mais c'est généré par du code, pas à la mano) Et c'est d'ailleurs ce qui me semble le plus efficace à la longue : le dev se fait chier à faire un truc chiadé, mais ensuite le type qui pond les contenus fournit un simple JSON (ou un panneau d'admin facile à implémenter en pur JS) tandis que le code utilise des colonnes optimisées à mort. RE: Comment stockez-vous vos quantités de ressources ? - Arnadus - 11-08-2013 Citation :Un système simple mais rigide Sans vouloir m'avancer, il semble y avoir un problème d'abstraction ici. Pourquoi ne pas considérer les ressources comme un type à part entière? (Et donc, pour parler au niveau BDD, comme une table) Si tu crées chaque fois de nouveaux champs dans chaque entité qui requiert (= est lié) au concept de ressource, évidemment, c'est mauvais pour l'évolutivité et la maintenabilité. Donc, pourquoi ne pas simplement extraire tes ressources dans une table dédiées? Et chaque entité qui aurait besoin de faire référence à ce concept de ressource serait lié (= foreign key) à une ligne dans cette table... Tout simplement. Citation :usage : Par exemple, un type de bête a une consommation et une capacité de récolte. Pour prendre un exemple plus concret, ton type "bête" aurait deux relations 1-1 vers la table "ressources". Ces deux relations seraient représentés par 2 foreign key. la première: "consommation_ressource_id" la deuxième: "capacite_recolte_id" et il en va de même pour la notion de coût, de prime etc... Tout ce qui touche au ressource de près ou de loin devra être en lien avec cette table. De cette manière, si un jour tu veux ajouter un type de ressource, tu n'auras qu'à le faire dans la table "ressource". RE: Comment stockez-vous vos quantités de ressources ? - niahoo - 11-08-2013 Comme modéliserais tu "la fourmi consomme 4 unités d'herbe ou 2 unités de feuille (qui en plus la soignent) par heure" avec ta solution ? RE: Comment stockez-vous vos quantités de ressources ? - Arnadus - 11-08-2013 Il est très difficile de répondre à cette question en ayant cet énoncé pour seul support. Mais si le concept de consommation doit également être raffiner, rien ne nous empêches de le faire. On peut donc imaginer une entité "consommation" ayant 2 attributs:
Concernant le soin, là c'est encore plus vague et donc plus difficile pour moi de répondre. Mais c'est toujours le même principe. Si le soin est attaché au concept de consommation, alors on attache un troisième attribut à l'entité consommation: "soin".
RE: Comment stockez-vous vos quantités de ressources ? - Sephi-Chan - 11-08-2013 J'avais envisagé MongoDB avant de réaliser que mes données de jeu étaient vraiment très relationnelles. J'ai donc préféré rester sur une base taillée pour ça. Pour la conservation en cache, je vais plutôt essayer de l'abstraire autrement car je ne suis pas fan des données hardcodées. Arnadus, dans la première modélisation que je décris, la ressource est bien un type à part entière. Ce n'est plus le cas dans les deux autres modélisation, qui sont en échanges plus simples et efficaces (tant que ma problématique n'évolue pas trop, bien sûr). Pour ce qui est de la nourriture, je vais partir sur des règles simples : la bête consomme ce qui la soigne en priorité si elle est blessée (sa priorité augmente avec la gravité de son état), en piochant dans ce qu'il y a en plus grande quantité d'abord. Certaines bêtes passent avant les autres (de la plus grosse à la plus petite). |