28-03-2017, 07:35 PM
Double-post, tant pis... Mais en réfléchissant un peu sur le chemin de la maison, ceci sera bien plus efficace (65k/6s chez moi, sachant que la 1ere procédure proposée en faisait en fait 65k/20s):
Note que pour 400k populations, il faut 70 secondes, c'est pas franchement top niveau complexité, mais au moins, cela n'explose pas.
Après, ça illustre ce que je disais sur les procédures: il sera toujours temps, plus tard, de trouver mieux (ou de monter en puissance, ou de changer de SGBD au pire). Vu la masse de calcul que tu demandes, de toute façon, je doute que le moindre système soit capable de le faire en un claquement de doigts (hors système bricolés maison, qui chargent tout en RAM ou autre).
SET PROFILING := 1;
-- Ca, c'est pour mon initialisation
DROP TABLE IF EXISTS `integers`;
CREATE TABLE integers (
n INT UNSIGNED NOT NULL,
PRIMARY KEY (`n`)
) ENGINE=InnoDB;
INSERT INTO integers (n) VALUES (0),(1),(2),(3)/*,(4),(5)*/;
INSERT INTO integers (n) (SELECT i.n+(SELECT COUNT(*) FROM integers)*j.n FROM integers AS i INNER JOIN integers AS j WHERE j.n > 0);
INSERT INTO integers (n) (SELECT i.n+(SELECT COUNT(*) FROM integers)*j.n FROM integers AS i INNER JOIN integers AS j WHERE j.n > 0);
INSERT INTO integers (n) (SELECT i.n+(SELECT COUNT(*) FROM integers)*j.n FROM integers AS i INNER JOIN integers AS j WHERE j.n > 0);
SELECT MAX(n) FROM integers;
-- Ca, c'est la nouvelle table de population (colonnes en plus)
DROP TABLE IF EXISTS population;
CREATE TABLE population (
id INT UNSIGNED NOT NULL,
id_joueur INT UNSIGNED NOT NULL,
moral DOUBLE DEFAULT 0,
eat DOUBLE DEFAULT 0,
PRIMARY KEY (`id`),
INDEX `idx_id_joueur` (`id_joueur`)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS `resources`;
CREATE TABLE resources (
id_joueur INT UNSIGNED NOT NULL,
quantite DOUBLE DEFAULT 0,
PRIMARY KEY(`id_joueur`)
) ENGINE=InnoDB;
INSERT INTO population (id, id_joueur) (SELECT n, CEIL(1000*RAND()) FROM integers);
INSERT INTO resources (id_joueur, quantite) (SELECT n, RAND()*100000 FROM integers WHERE n BETWEEN 1 AND 1000);
-- Fin de l'initialisation
-- Début du vrai algo
-- Là, c'est à toi de fixer l'algo disant combien de ressources veut la population
UPDATE population SET eat = RAND()*1000;
UPDATE population p
INNER JOIN resources r ON r.id_joueur = p.id_joueur
SET p.moral = IF(r.quantite >= p.eat, p.moral + 20, p.moral - 20),
r.quantite = IF(r.quantite >= p.eat, r.quantite - p.eat, r.quantite);
SHOW PROFILES;
SET PROFILING := 0;
Note que pour 400k populations, il faut 70 secondes, c'est pas franchement top niveau complexité, mais au moins, cela n'explose pas.
Après, ça illustre ce que je disais sur les procédures: il sera toujours temps, plus tard, de trouver mieux (ou de monter en puissance, ou de changer de SGBD au pire). Vu la masse de calcul que tu demandes, de toute façon, je doute que le moindre système soit capable de le faire en un claquement de doigts (hors système bricolés maison, qui chargent tout en RAM ou autre).