28-03-2017, 02:12 PM
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
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
/*
-- Init de la table, ~1M de lignes
CREATE TABLE IF NOT EXISTS `tst` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`value` INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2097153
;
-- Ouais, y'a peut-être mieux, mais osef
INSERT INTO tst (id) (SELECT 1);
INSERT INTO tst (id) (SELECT (id+1) FROM tst);
INSERT INTO tst (id) (SELECT (id+2) FROM tst);
INSERT INTO tst (id) (SELECT (id+4) FROM tst);
INSERT INTO tst (id) (SELECT (id+8) FROM tst);
INSERT INTO tst (id) (SELECT (id+16) FROM tst);
INSERT INTO tst (id) (SELECT (id+32) FROM tst);
INSERT INTO tst (id) (SELECT (id+64) FROM tst);
INSERT INTO tst (id) (SELECT (id+128) FROM tst);
INSERT INTO tst (id) (SELECT (id+256) FROM tst);
INSERT INTO tst (id) (SELECT (id+512) FROM tst);
INSERT INTO tst (id) (SELECT (id+1024) FROM tst);
INSERT INTO tst (id) (SELECT (id+2048) FROM tst);
INSERT INTO tst (id) (SELECT (id+4096) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*2) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*4) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*8) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*16) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*32) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*64) FROM tst);
INSERT INTO tst (id) (SELECT (id+8192*128) FROM tst);
*/
DELIMITER $
DROP PROCEDURE IF EXISTS tstproc;
CREATE PROCEDURE `tstproc`(
IN howmany INT)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
SET @i := howmany;
SET @prefix := FLOOR(1000*RAND());
START TRANSACTION READ WRITE;
WHILE @i > 0 DO
UPDATE tst SET tst.value = @prefix WHERE tst.id = @i;
SET @i := @i - 1;
END WHILE;
COMMIT;
END$
DELIMITER ;
-- 200ms en local pour 10k lignes;
-- y'a évidemment mieux en optimisant le contenu de la procédure,
-- mais c'est parfois un temps acceptable
CALL tstproc(10000);