15M 行のテーブルを反復処理する select ステートメントで開くストアド プロシージャがあります(このテーブルは、大きな CSV の単純なインポートです)。CURSOR
各行のさまざまな部分を 3 つの異なるテーブルに挿入して、そのデータを正規化する必要があります(自動更新 ID を取得し、それらを外部キー制約で使用するなど)。
そこで、単純なストアド プロシージャ openCURSOR
をFETCH
作成し、フィールドを varialbes に変換し、3 つの挿入ステートメントを実行しました。
私は小さなDBサーバー、デフォルトのmysqlインストール(1 cpu、1.7GB RAM)を使用しています。このタスクに数時間かかることを望んでいました。私は 24 時間以上で、トップは85% の無駄な CPUを示しています。
私はある種のひどい非効率性を持っていると思います。タスクの効率を改善するためのアイデアはありますか? それとも、ボトルネックがどこにあるかを判断するだけですか?
root@devapp1:/mnt/david_tmp# vmstat 10
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 1 256 13992 36888 1466584 0 0 9 61 1 1 0 0 98 1
1 2 256 15216 35800 1466312 0 0 57 7282 416 847 2 1 12 85
0 1 256 14720 35984 1466768 0 0 42 6154 387 811 2 1 10 87
0 1 256 13736 36160 1467344 0 0 51 6979 439 934 2 1 9 89
DROP PROCEDURE IF EXISTS InsertItemData;
DELIMITER $$
CREATE PROCEDURE InsertItemData() BEGIN
DECLARE spd TEXT;
DECLARE lpd TEXT;
DECLARE pid INT;
DECLARE iurl TEXT;
DECLARE last_id INT UNSIGNED;
DECLARE done INT DEFAULT FALSE;
DECLARE raw CURSOR FOR select t.shortProductDescription, t.longProductDescription, t.productID, t.productImageURL
from frugg.temp_input t;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN raw;
read_loop: LOOP
FETCH raw INTO spd, lpd, pid, iurl;
IF done THEN
LEAVE read_loop;
END IF;
INSERT INTO item (short_description, long_description) VALUES (spd, lpd);
SET last_id = LAST_INSERT_ID();
INSERT INTO item_catalog_map (catalog_id, catalog_unique_item_id, item_id) VALUES (1, CAST(pid AS CHAR), last_id);
INSERT INTO item_images (item_id, original_url) VALUES (last_id, iurl);
END LOOP;
CLOSE raw;
END$$
DELIMITER ;