Boucle UPDATE, RAND - 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 : Boucle UPDATE, RAND (/showthread.php?tid=7787) |
Boucle UPDATE, RAND - MeTaLLiQuE - 28-03-2017 Bonsoir, Je rencontre un soucis... Facile à développer mais la meilleure solution pour flinger mon serveur... En gros, j'ai une table qui pourra contenir (sur le moyen terme) des millions de lignes... Chaque colonne contiendra en majorité des données de type INT (int, tinyint, ...) Dans mon code PHP, je fais un calcul pour savoir si toutes les populations (Au nombre de 3 types différents) ont reçues leur nourriture (il y en a 10 différentes). Si toutes les populations ont reçues leur nourriture, le moral augmente individuellement de 20% s'il y a une population qui n'a pas reçue au moins une nourriture elle perd individuellement 20% EXEMPLE : Mes trois types de populations (et leur nombre) sont : 100 serfs, 50 artisans, 10 bourgeois Les ressources différentes : blé, viande, pain, peau, etc.... Je vérifie donc pour chaque ressource si j'arrive à nourrir les 100 serfs, puis les 50 artisans puis les 10 bourgeois Si j'arrive à tous les nourrires j'augmente individuellement de 20% leur moral Si je n'arrive à nourrir que 80 serfs en blé = 20% à tous les serfs que j'aurais nouris et les 20 serfs restant verront leur moral baissé de 20% et ce, à chaque ressource et sur chaque type de la population. (les populations qui se verront augmenter et baisser de 20% sont choisis aléatoirement, je ne vous parle pas du gouffre avec la fonction RAND...). Je ne sais pas comment arriver à optimiser à sachant que ça ferait au total 100*10+50*10+10*10 = 1600 requêtes UPDATE pour un seul joueur dans cet exemple... Je ne pense pas qu'il soit possible de faire comme les INSERT INTO en les regroupant tous et exécuter qu'une seule fois la requête... Je vous mets un bout de code au caou si vous n'arrivez pas à comprendre ce que je veux dire...
Merci d'avance RE: Boucle UPDATE, RAND - Xenos - 28-03-2017 Citation :Dans mon code PHP, je fais un calcul pour savoir si toutes les populations (Au nombre de 3 types différents) ont reçues leur nourriture (il y en a 10 différentes).Fais-le dans le MySQL, par procédure stockée. Ca dépote (perso, sur Iamanoc, un petit réseau social pour personnages fictifs, j'ai fait quelques tests et tout traiter dans le serveur SQL donne des temps de réponse de <50ms même avec 1 million de messages et d'évènements). Une boucle de requête UPDATE n'est alors plus un problème (car le temps réseau ne se glisse pas au milieu). Je la présenterai dans quelques jours cette archi, je pense que cela pourra en intéresser quelques uns (dont toi ) A défaut, si tu ne veux pas changer d'archi, utilise INSERT INTO ... (id, ...) VALUES (.../* là, tu groupes un batch de 500*/...) ON DUPLICATE KEY UPDATE moral=VALUES(moral), viande=VALUES(viande),... /*là, tu liste les colonnes de données */. Cela ne fera qu'une requête qui a pour principe d'écraser la ligne de donnée si une clef UNIQUE (la PRIMARY KEY de l'id, généralement) existe déjà. Cela permet d'émuler des "UPDATE par batch". RE: Boucle UPDATE, RAND - MeTaLLiQuE - 28-03-2017 Je n'ai jamais fait de procédure stockée. Je regarderai de ce côté voir. Et j'attends avec impatience alors (: Concernant le INSERT INTO ON DUPLICATE KEY UPDATE, je ne connais pas l'ID (la clé primaire) car je voulais l'appliquer sur un RAND En gros, à la version gros porc, ça donnerai :
RE: Boucle UPDATE, RAND - Ter Rowan - 28-03-2017 je ferais autrement : - dans la table joueur ou village (ou ensemble de personnages que tu traites) tu ajoutes un champ " % nourris" que tu alimentes d'après tes calculs - dans la table personnage tu rajoutes un champ "score nrt" ca donne un truc : id personnage / id village / score nrt / moral là tu fais une ou deux requêtes (je ne maitrise pas assez sql) pour : 1) définir un rand(1 -> 100) pour le score nrt de chaque personnage 2) si score nrt de personnage <= %nourris de id village alors il mange à sa faim, sinon il ne mange pas à sa fin et donc update en conséquence. mathématiquement c'est pas terrible (puisque statistiquement tu peux avoir bcp plus ou bcp moins de personnages nourris que la cible du village) mais d'un point de vue game play ça peut s'expliquer, des restes du coup d'avant (vive le pain perdu), du rationnement, de la déperdition (à mort les rats), etc... RE: Boucle UPDATE, RAND - MeTaLLiQuE - 28-03-2017 Le moral n'est pas basé uniquement s'il a été nourri ou pas... Si la population travail (ou pas) ca impactera le moral, s'il est'trop taxé ou pas, ca impactera son moral, etc. ... Puis ca reviendrai au même, il y aurait autant d'update car faudrait mettre à jour ligne par ligne... RE: Boucle UPDATE, RAND - Xenos - 28-03-2017 Perso, je le tenterai sous la forme simple d'un UPDATE population p SET p.moral = p.moral + (SELECT +/-20 ... FROM consommations) de sorte que la subquery SELECT fournisse + ou - 20 en fontion des ressources disponibles (si cette subquery est faisable, j'ai pas trop regardé la logique métier). Sinon, en restant hors SQL, tu peux déjà changer ton id = $donSelectTroupe en un IN (donSelectTroupe) qui ne fera qu'un UPDATE au lieu de 50. Après, au lieu d'exécuter la query à cet endroit, tu peux stocker la liste de ces IDs et n'exécuter qu'un seul UPDATE ... WHERE IN ($maListeStockee) à la fin de la boucle. Même principe pour l'autre UPDATE (où il te faut alors stocker la liste [id du joueur => [categories]]) RE: Boucle UPDATE, RAND - MeTaLLiQuE - 28-03-2017 je vais essayer, par contre, pour confirmer il n'y a pas de limite de modifications possibles sir l'update ? Je peux modifier 1, 100, 100000, lignes en même temps ? Merci RE: Boucle UPDATE, RAND - Ter Rowan - 28-03-2017 on peut updater autant de lignes en une seule requête que l'on veut, il suffit d'avoir les bonnes conditions (et ma proposition correspond à créer les conditions pour faire une seule requête) c'est sur que si tu fais un update par record ça risque pas de marcher RE: Boucle UPDATE, RAND - Xenos - 28-03-2017 Si tu lockes la table avant de faire tes updates (START TRANSACTION READ WRITE par exemple), que ceux-ci sont simples (ie portent sur un ID PRIMARY) et qu'ils sont faits dans une procédure stockée, alors un UPDATE par record est acceptable (y'a quasiment toujours moyen de faire bien mieux, mais cela tient la charge). Cet exemple met 10k lignes à jour en ~200ms sur MySQL 5.7; c'est franchement pas optimal, okay, mais c'est l'un des intérêts de l'approch à procédures: il sera toujours temps de faire de meilleures queries dans cette procédure quand les lenteurs se feront sentir
RE: Boucle UPDATE, RAND - Ter Rowan - 28-03-2017 jamais vu que c'était une bonne pratique de faire des update ligne à ligne... |