Bonjour à tous,
Je travaille avec de gros volumes et je tente d'optimiser mes traitements.
Je pourrais intégrer le parallélisme dans mes traitements. Je pourrais aussi effectuer certaines "opérations hors base", en implémentant des algorithmes spéciaux, mais complexes..
Sur de gros volumes de données, je constate que la construction suivante est "colossalement contre-performante" :
Par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part UPDATE ... WHERE ... IN (SELECT ...);
La procédure suivante s'exécute beaucoup plus rapidement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 DROP TABLE IF EXISTS `A`; CREATE TABLE IF NOT EXISTS `A` ( `idA` INT NOT NULL AUTO_INCREMENT, `value` INT NOT NULL, PRIMARY KEY (`idA`) ) ENGINE = InnoDB; DROP TABLE IF EXISTS `B`; CREATE TABLE IF NOT EXISTS `B` ( `idB` INT NOT NULL AUTO_INCREMENT, `fk_idA` INT NOT NULL, `value` INT NOT NULL, PRIMARY KEY (`idB`), INDEX `idfk_idA` (`fk_idA` ASC), INDEX `idvalue` (`value` ASC) ) ENGINE = InnoDB; CREATE TEMPORARY TABLE `tmpTable` SELECT `B`.`fk_idA` AS `idA` FROM `B` WHERE `B`.`value` > 3; UPDATE `A` SET `A`.`value` = 10 WHERE `A`.`idA` IN (SELECT `tmpTable`.`idA` AS `idA` FROM `tmpTable`);
Ce que je recherche à faire ressemble à un "UPDATE avec jointure" : UPDATE d'une table en fonction d'un critère calculé sur une autre table.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 DELIMITER // DROP PROCEDURE IF EXISTS myProc // CREATE PROCEDURE myProc() BEGIN DECLARE n INT DEFAULT 0; #- Indicateur de "fin de curseur". DECLARE done INT DEFAULT 0; #- Curseur sur les valeurs distinctes de `id_cdr`. DECLARE updateCur CURSOR FOR SELECT `idA` AS `idA` FROM `tmpTable`; #- Curseur de détection de fin de sélection. DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; #- On sélectionne les valeurs sur lesquelles on va travailler. DROP TABLE IF EXISTS `tmpTable`; CREATE TEMPORARY TABLE `tmpTable` SELECT `B`.`fk_idA` AS `idA` FROM `B` WHERE `B`.`value` > 3; #- Lancement de l'opération. SET done = 0; OPEN updateCur; FETCH updateCur INTO n; WHILE done = 0 DO UPDATE `A` SET `A`.`value` = 10 WHERE `A`.`idA`=n; FETCH updateCur INTO n; END WHILE; CLOSE updateCur; END // DELIMITER ;
Quelqu'un connaît-il une procédure plus performante pour parvenir au même résultat?
Remarque :
Merci à tous,
Code : Sélectionner tout - Visualiser dans une fenêtre à part Server version: 5.1.49-0.dotdeb.0 (Debian)
A+
Partager