JeuWeb - Crée ton jeu par navigateur
[MySQL] IF et produits de champs - 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 : [MySQL] IF et produits de champs (/showthread.php?tid=4000)

Pages : 1 2


[MySQL] IF et produits de champs - Holy - 25-05-2009

B'soir à tous,

Voilà, dans le cadre du développement de mon site je me retrouve avec un petit soucis (ou pas). Pour faire simple, j'ai une table bataillon où l'on retrouve 4 champs:
Code :
state | player | pattern | number
Jusque là, rien de bien difficile. Je vais vous filer deux trois exemples de lignes histoire que vous visualisiez bien la table
Code :
HER | 1 | sword | 10
DOL | 1 | distance | 20
HER | 5 | cavalry| 10

La lecture est assez facile à faire, seulement à ces bataillons sont reliées des caractéristiques (exemple: place prise dans un bastion, puissance, etc.). Ces caractéristiques se trouvent dans un tableau multidimensionnel statique qui ne se trouve donc pas en BDD.

Donc par exemple quand je dois calculer l'occupation d'un bastion, ou la puissance totale sur un bastion, je dois bricoler ma requête en tapant une fonction de ce type:
Code :
SELECT SUM( IF(b.pattern = 'sword' AND pi.nation = 'marchand', 1*b.number, 0) + IF(b.pattern = 'middlesword' AND pi.nation = 'marchand', 1*b.number, 0)) as numb, b.state FROM battalion_tbl b ...

Je ne vous ai mis ici que le début avec deux unités. Le fait est que j'ai énormément d'unités dans le jeu, ce qui fait que les requêtes sont très longues, et un peu sinueuses.

Evidemment, je ne construis pas mes requêtes manuellement, j'ai un beau foreach qui parcourt tout mon tableau pour en faire une jolie requête prête à l'emploi (donc niveau maintenance, c'est pépère). Mais ça marche et niveau perf j'arrive à des résultats relativement normaux (exemple: calcul de 5 bastions sur plus de 400 joueurs (2300 lignes), traitement en 0.0098 sec.).

Je me demandais donc si il y avait une autre solution, plus lisible, plus logique en somme. Je dois bien avouer que j'ai vraiment bidouillé le truc, mais je n'avais rien trouvé de pertinent dans la doc MySQL ^^


RE: [MySQL] IF et produits de champs - Argorate - 25-05-2009

Salut,

J'avoue que j'ai du mal à suivre ta requête du bas là, mais moi généralement je fais les if dans le code, et le SQL "simplifié" derrière, ça t’aiderait surement que les choses soit plus claire et des requêtes plus légère et moins longue à exécuter en plus...


RE: [MySQL] IF et produits de champs - Allwise - 26-05-2009

Pour les grosses requêtes, ou les requêtes qui nécessitent de faire des traitements, les procédures stockées sont une bonne solution. Elles te permettent de délocaliser le traitement dans une fonction mysql en gros, et tu appelles ces fonctions comme tu ferais n'importe quelle requête.
Tu gagneras ainsi en visibilité.

Sinon, je ne connais pas ton modèle de données, mais tu peux aussi plancher sur des optimisations qui te permettraient de te passer de toutes ces conditions. Par exemple là, la donnée que tu calcules semble dépendre de 2 facteurs : pattern et nation. On pourrait envisager une table "bastion_force" ( si c'est bien la force, mais peu importe ) avec dedans les champs pattern, nation, et force.

Pour chaque couple pattern & nation, tu as une force. Tu pourrais donc remplacer toutes ces conditions par une simple multiplication.


RE: [MySQL] IF et produits de champs - Holy - 26-05-2009

@Argorate: Le problème ici c'est que si je fais le traitement dans le code, je vais me taper des boucles assez conséquentes en raison des spécificités de chaque ligne.
Dans le sens où pattern me donne le type de l'unité, mais sword peut correspondre à un orc, un humain, etc. (ce qui fait que je ne peux pas rassembler mes résultats vu que les caractéristiques changent en fonction de la faction). Enfin en gros, faire le traitement derrière c'est accroitre mon champ de travail.

Et d'ailleurs c'est une solution qui montre rapidement ses limites si je dois par exemple recalculer toute la puissance de tous les joueurs du jeu. C'est assez difficile à expliquer, mais disons que chaque joueur peut avoir 20 types d'unités, j'ai 700 joueurs sans pub, ça me fait directement 1400 champs, donc 1400 requêtes (impossible de faire des jointures en update), ce qui est quand même conséquent. Alors qu'en utilisant cette technique de condition (dont la lisibilité est limité, ça c'est clair), j'ai qu'une seule requête à faire et c'est dans la poche.

Mais c'est vraiment du à la spécificité du jeu et à sa complexité (et richesse) technique.

(26-05-2009, 12:19 AM)Allwise a écrit : Pour les grosses requêtes, ou les requêtes qui nécessitent de faire des traitements, les procédures stockées sont une bonne solution. Elles te permettent de délocaliser le traitement dans une fonction mysql en gros, et tu appelles ces fonctions comme tu ferais n'importe quelle requête.
Tu gagneras ainsi en visibilité.

Sinon, je ne connais pas ton modèle de données, mais tu peux aussi plancher sur des optimisations qui te permettraient de te passer de toutes ces conditions. Par exemple là, la donnée que tu calcules semble dépendre de 2 facteurs : pattern et nation. On pourrait envisager une table "bastion_force" ( si c'est bien la force, mais peu importe ) avec dedans les champs pattern, nation, et force.

Pour chaque couple pattern & nation, tu as une force. Tu pourrais donc remplacer toutes ces conditions par une simple multiplication.
Ouep, j'avais déjà eu cette idée là qui est assez facile à mettre en place.
Le truc c'est que j'aimerais éviter de multiplier les endroits où se trouvent une même information (ici en l'occurrence dans un fichier sérialisé).

J'ai deux ou trois requêtes "gigantesques" de ce type sur tout le site, donc c'est plutôt ponctuel.

Je suis par contre très intéressé par la première solution. J'avais déjà entendu parler des procédures mais sans vraiment m'y attarder. Je vais voir ce que ça donne ^^


RE: [MySQL] IF et produits de champs - Argorate - 26-05-2009

Ce que je t'ai dis n'allez pas contre les procédure stocker! Wink

Le TRANSACT SQL c'est du code (et un langage) comme un autre qui te permet tout plein de IF, des boucle si besoin ect.

Bonne chance.


RE: [MySQL] IF et produits de champs - Roworll - 26-05-2009

Quelques remarques.

TRANSACT-SQL (ou T-SQL) est le nom donné à l'extension SQL propriétaire à Sybase/Microsoft. La syntaxes et les capacités su langage sont assez éloignées de MySQL.
T-SQL s'appuie sur une structure complexe, construisant et stockant dans un environnement SQL Server des plans de requêtes basés sur les statistiques de la BDD. MySQL propose(ra) une compatibilité avec la syntaxe sans atteindre toutes ses subtilités.

D'ailleurs, l'utilisation à outrance de IF, CASES et autres instructions conditionnelles lors de la récupération des données n'est pas la meilleure manière d'obtenir de bonnes performances. Les utiliser de manière procédurale par contre ne pose pas de problèmes.

Holy, dans l'exemple que tu donnes, je vois que tu as une sorte de règle.
Pattern couplé à Nation donne un multiplicateur pour Number

Pourquoi ne pas transformer cette règle en table et faire l'utiliser dans une jointure pour obtenir ton résultat ?
Code :
Pattern       | Nation     | Coeff
----------------------------------
'sword'       | 'marchand' | 1
'middlesword' | 'marchand' | 1
'sword'       | 'guerrier' | 2
'middlesword' | 'guerrier' | 2

Avec cette table utilisée dans une jointure, tu peux calculer tes valeurs sans recourir aux IF. Ce sera plus naturel (et à terme surement plus performant) pour le moteur MySQL


RE: [MySQL] IF et produits de champs - Holy - 26-05-2009

(26-05-2009, 08:04 AM)Roworll a écrit : Pourquoi ne pas transformer cette règle en table et faire l'utiliser dans une jointure pour obtenir ton résultat ?
Code :
Pattern       | Nation     | Coeff
----------------------------------
'sword'       | 'marchand' | 1
'middlesword' | 'marchand' | 1
'sword'       | 'guerrier' | 2
'middlesword' | 'guerrier' | 2

Avec cette table utilisée dans une jointure, tu peux calculer tes valeurs sans recourir aux IF. Ce sera plus naturel (et à terme surement plus performant) pour le moteur MySQL
C'est la solution que proposait Allwise et à laquelle j'avais pensé également. Seulement ce que je disais, c'est que ça m'embête dans la mesure où j'aurais deux fois une même info à différents endroits. Mais cela étant dit, étant donné que j'ai une procédure centralisée pour la gestion de mes unités, je peux très bien remodifier automatiquement ma table tout en ne l'utilisant que quand j'en ai besoin (et utiliser mes fichiers sérialisés le reste du temps).

Je pense que je vais procéder de cette façon. Merci pour les infos ^^


RE: [MySQL] IF et produits de champs - Holy - 26-05-2009

Je viens de mettre en pratique la solution évoquée, et j'ai un résultat plutôt surprenant.

J'ai un temps de traitement près de deux fois supérieurs en utilisant la technique des jointures (moyenne de 0.0220 sur 100 000 req).
Je me doute que plus j'aurai d'unités, plus la première requête (IF) sera lourde.


RE: [MySQL] IF et produits de champs - Allwise - 26-05-2009

Tu vas piocher les infos dans une table supplémentaire, néanmoins avec les index où il faut le temps de traitement devrait pas être excessivement long. 0.0220 ça reste quand même un bon temps pour une requête, faudrait que tu simules un cas réel pour voir ce que ça donne.


RE: [MySQL] IF et produits de champs - keke - 27-05-2009

(26-05-2009, 06:08 PM)Holy a écrit : Je viens de mettre en pratique la solution évoquée, et j'ai un résultat plutôt surprenant.

J'ai un temps de traitement près de deux fois supérieurs en utilisant la technique des jointures (moyenne de 0.0220 sur 100 000 req).
Je me doute que plus j'aurai d'unités, plus la première requête (IF) sera lourde.

Pour suppléer à la réponse de Allwise (tout intelligent ? toujours intelligent ?) pourrais-tu afficher ta requête contenant les jointures ? Il y a peut-être de l'amélioration à y apporter.

kéké