質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

2回答

2160閲覧

高速にテーブルの移動を行いたい

aglkjggg

総合スコア769

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2015/12/20 10:38

sql

1DROP PROCEDURE IF EXISTS p1; 2 3CREATE PROCEDURE p1() 4BEGIN 5 DECLARE done INT DEFAULT 0; 6 DECLARE item_id INT; 7 DECLARE cur CURSOR FOR SELECT item_id FROM table1 WHERE category=1; 8 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 9 OPEN cur; 10 11 WHILE done = 0 DO 12 FETCH cur INTO inviteCode; 13 14 # table2に挿入する 15 INSERT INTO table2 (SELECT * FROM table1 WHERE table1.item_id = item_id); 16 # table1から消す 17 DELETE FROM table1 WHERE table1.item_id = item_id; 18 19 END WHILE; 20 21 CLOSE cur; 22END; 23 24CALL p1();

このようなプロシージャでcategory=1のデータをtable1からtable2に移動させています。
データが1,000行/秒ほどで移動されているのですが、移動対象のデータが5,000万行あります。

できるだけ早くテーブルの移動を行いたいのですがどこを改善すればよろしいでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

table1を2回SELECTしているのを1回にまとめてみては?

DECLARE cur CURSOR FOR SELECT item_id FROM table1 WHERE category=1;

DECLARE cur CURSOR FOR SELECT ***** FROM table1 WHERE category=1;

INSERT INTO table2 (SELECT * FROM table1 WHERE table1.item_id = item_id);
↓ INSERT INTO table2 **VALUES(....)** ;

table1.item_id が AUTOINCREMENT のように現在より大きな値が設定されることが保障されているなら、

SELECT MAX(item_id) FROM table1 WHERE category=1);
でitem_idの最大値を求めて、

INSERT INTO table2 (SELECT * FROM table1 WHERE category=1 AND item_id <= item_idの最大値);

DELETE FROM table1 WHERE category=1 AND item_id <= item_idの最大値;
で対応できるかもしれません。

投稿2015/12/22 23:44

編集2015/12/23 04:46
Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

category=1のデータを入れるならwhileせずに一気にやった方が早そうな気がします。(大して効果ないかもしれないけど)
x INSERT INTO table2 (SELECT * FROM table1 WHERE table1.item_id = item_id);
○ INSERT INTO table2 (SELECT * FROM table1 WHERE table1.category=1);

insertとdeleteどちらが時間かかってるかも気になりますね。
#DELETE FROM table1 WHERE table1.item_id = item_id;
をwhile毎にやらずに、CLOSE cur;後に一気にdeleteしてもいいような気がします。
ただ、件数が多いとdeleteは非常に重いので、table1.categoryにパーティションを付けて最後に対象のパーティションをDROPするという事が出来る条件なら試してみてもいいかもしれません。

まあ、whileする必要あるのかな?って。

処理前にauto commitをoff、最後にcommitすれば高速化するかもしれないですがPROCEDUREで試した事はないです。
用途はよくわからないですが、table2にindex付けないとか。

投稿2015/12/20 12:10

ooi

総合スコア43

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aglkjggg

2015/12/20 13:18

回答ありがとうございます。 `table1`のデータは常に増え続けているため`INSERT`した後に`DELETE`すると`table2`に移っていないデータまで消えてしまう恐れがあるためwhileで処理しました。 AUTO COMMIT OFFの件試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問