
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
補足、プロシージャを使って10のn乗件単位でやるならこうかな
(思ったより速くなったけど、まだ改善の余地あり)
一度バルクSQLをつくってから流し込むので
あまり長すぎるSQLを書くとオーバーフローする可能性があります。
要素数やレコード長によりますが1000件単位くらいが妥当かなと
DROP PROCEDURE IF EXISTS MYPROCEDURE4;
DELIMITER //
CREATE PROCEDURE MYPROCEDURE4()
BEGIN
DECLARE a BLOB;
DECLARE done INT DEFAULT 0;
DECLARE CUR CURSOR FOR
SELECT
CONCAT('INSERT IGNORE INTO `tbl2` VALUES('
,GROUP_CONCAT('\'',id,'\',\'',data,'\',\'',val,'\'' separator '),(')
,')') as x
FROM `tbl1`
GROUP BY TRUNCATE(id,-2);/* PER1=0, PER10=-1, PER100=-2, PER1000=-3*/
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
SET group_concat_max_len = 10000000;
OPEN CUR;
REPEAT
FETCH CUR INTO a;
IF NOT done THEN
SET @sql=a;
PREPARE stmt from @sql;
EXECUTE stmt;
END IF;
UNTIL done END REPEAT;
CLOSE CUR;
END
//
DELIMITER ;
TRUNCATE `tbl2`;
CALL MYPROCEDURE4;
No.3
- 回答日時:
試しにプロシージャをつかってテストをしてみました
パターンは3つ
(1)1レコードごとに投入を繰り返す
(2)複数レコードをまとめて投入を繰り返す
(3)INSERT ・・・ SELECT で投入する
質問者さんは(3)は遅いとのことでしたが
実際やってみたところ早い順 (3)>(1)>(2)でした
実際圧倒的に(3)が速いようなので、プロシージャではあきらめて#2で提案したように
mysqldumpなどで処理する方がよいかもしれませんね。
(プロシージャだとCONCATで同じデータをくりかえし処理するので無駄がおおい?)
テスト
CREATE TABLE `tbl1`(`id` INT NOT NULL UNIQUE,`data` VARCHAR(100),`val` DOUBLE);
CREATE TABLE `tbl2`(`id` INT NOT NULL UNIQUE,`data` VARCHAR(100),`val` DOUBLE);
※1000データをつくる
DROP PROCEDURE IF EXISTS MYPROCEDURE1;
DELIMITER //
CREATE PROCEDURE MYPROCEDURE1()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i<1000 DO
INSERT IGNORE INTO tbl1 VALUES(i,'x',RAND());
SET i=i+1;
END WHILE;
END
//
DELIMITER ;
TRUNCATE `tbl2`;
CALL MYPROCEDURE1;
(1)1レコード毎投入:平均して1秒前後
DROP PROCEDURE IF EXISTS MYPROCEDURE2;
DELIMITER //
CREATE PROCEDURE MYPROCEDURE2()
BEGIN
DECLARE a INT;
DECLARE b VARCHAR(100);
DECLARE c DOUBLE;
DECLARE done INT DEFAULT 0;
DECLARE CUR CURSOR FOR
SELECT id,data,val FROM tbl1;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN CUR;
REPEAT
FETCH CUR INTO a,b,c;
SET @sql='INSERT IGNORE INTO `tbl2` VALUES ';
SET @sql=CONCAT(@sql,'(\'',a,'\',\'',b,'\',\'',c,'\')');
PREPARE stmt from @sql;
EXECUTE stmt;
UNTIL done END REPEAT;
CLOSE CUR;
END
//
DELIMITER ;
TRUNCATE `tbl2`;
CALL MYPROCEDURE2;
(2)100レコードをまとめて投入を繰り返す:平均して1.4秒くらい
DROP PROCEDURE IF EXISTS MYPROCEDURE3;
DELIMITER //
CREATE PROCEDURE MYPROCEDURE3()
BEGIN
DECLARE a INT;
DECLARE b VARCHAR(100);
DECLARE c DOUBLE;
DECLARE count INT DEFAULT 0;
DECLARE done INT DEFAULT 0;
DECLARE CUR CURSOR FOR
SELECT id,data,val FROM tbl1;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN CUR;
REPEAT
FETCH CUR INTO a,b,c;
IF count>100 THEN
SET count=0;
END IF;
IF count=0 THEN
SET @sql='INSERT IGNORE INTO `tbl2` VALUES ';
ELSE
SET @sql=CONCAT(@sql,',');
END IF;
SET @sql=CONCAT(@sql,'(\'',a,'\',\'',b,'\',\'',c,'\')');
PREPARE stmt from @sql;
EXECUTE stmt;
SET count=count+1;
UNTIL done END REPEAT;
CLOSE CUR;
END
//
DELIMITER ;
CALL MYPROCEDURE3;
(3)INSERT ・・・ SELECT で投入:平均0.01秒くらい
TRUNCATE `tbl2`;
INSERT tbl2 SELECT * FROM tbl1;
No.1
- 回答日時:
>プロシージャを作成してselectした結果で
>バルクinsertをしようと思うのですが
その通りやればいいのでは?
ちなみに100万件のデータをどうやって取ってくるつもりか
書いていないので、書きようがないのですが
たぶん1発でやるといろいろオーバーフローしそうなので、
1万件ずつくらいで分割しながらやるとよいです
INSERT INTO テーブル VALUESに対して(?,?,・・・・)という受け皿をつくって
$stmt = $pdo->prepare( $query);
$stmt->execute($data);
のようにすればよいでしょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL mysqlで INSERT と SELECTの用途は 1 2022/04/01 00:45
- MySQL 下の画像はSQLの4大命令の性質をまとめたものであるらしいです UPDATE INSERT DELE 1 2023/06/07 15:36
- Visual Basic(VBA) ExcelVBA No.を自動連番で設定をしながらデータ入力をしたい 2 2022/08/03 18:19
- MySQL 次の時間帯の勝率の合計を求めるSQL文 1 2023/07/04 17:12
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- Visual Basic(VBA) データのある範囲を選択するVBAについて 2 2022/09/03 00:20
- Excel(エクセル) エクセルのマクロでコピー後の貼り付け先を毎回指定したところにしたい 5 2022/08/12 10:47
- MySQL SQLです。下記の問合せを行うクエリを、PhpMyAdminで作成して実行せよ。 「昨年の各月の総降 1 2023/07/01 00:32
- Visual Basic(VBA) 動きっぱなしです。止め方とプロシージャの間違いを教えて下さい! 5 2022/08/15 23:08
- MySQL 共通点はあります。何が違うのでしょうか? 1 2023/01/27 05:22
このQ&Aを見た人はこんなQ&Aも見ています
-
insertを高速化させたい
その他(データベース)
-
oracleのinsert select性能
Oracle
-
SQLServer Insertが遅い
SQL Server
-
-
4
ACCESSで一括処理する方法
その他(データベース)
-
5
ORA-01013のエラーについて経験のある方お願いします。
Oracle
-
6
Dosブロンプトでtabを出力したい
その他(プログラミング・Web制作)
-
7
日付型のフィールドに空白を入れる方法を教えてください
その他(データベース)
-
8
ROWNUMでUPDATEをしたいのですが・・・。
Oracle
-
9
selectした結果の余計な余白を取るにはどうしたらよいのでしょうか
Oracle
-
10
Viewにインデックスは張れますか?
Oracle
-
11
データを削除しても表領域の使用率が減りません
Oracle
-
12
テーブルに主キーを作らないデメリットは?
その他(Microsoft Office)
-
13
select insertで複数テーブルから値を取得したい
Oracle
-
14
sqlで、600行あるテーブルを100行毎に分けてcsvファイルに書き出す方法を教えてください。
SQL Server
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
タグを記録したテーブルの書き...
-
Webで、図形描画を行いたい。
-
データの連番
-
深い人、浅い人の判断
-
Yes/No型にチェックを入れたい
-
VMware Player でCD-ROMドライ...
-
2つのテーブルを繋げて条件をつ...
-
親と子供が複数のSQL取得方法
-
このようなテーブルを取得するS...
-
Access 複数のフィールドからク...
-
MySQLでのランキングの生成方法...
-
プロシジャー一覧の取得
-
MySQLで特定の条件のレコードを...
-
エクセルで最後の文字だけ置き...
-
ワラスボについて
-
'id'を無視して、外部ファイル...
-
mysql 検索方法
-
MySQLでの複数テーブル(4つ...
-
OracleでINSERT文のループ
-
これなんですか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
エクセルの関数について教えて...
-
select文のwhere句に配列を入れ...
-
VIEWの元のテーブルのindexって...
-
エラー 1068 (42000): 複数の主...
-
SQLにて特定の文字を除いた検索...
-
【Transact-sql】 execの結果を...
-
マイクラPC版のコマンドで効率...
-
SQL Left Join で重複を排除す...
-
sqlで、600行あるテーブルを100...
-
複数テーブルのGROUP BY の使い...
-
WordpressのContact form 7でzi...
-
クエリ表示と、ADOで抽出したレ...
-
SQLサーバから、項目の属性(型...
-
selectした大量データをinsert...
-
Access パラメータクエリをcsv...
-
副問合せの書き方について
-
inner joinをすると数がおかし...
-
insertを高速化させたい
-
[MySQL] 3つのテーブルの結合で...
おすすめ情報
回答ありがとうございます。
プロシージャ内で、大量データをselectして
数件ずつバルクinsertしたいのですがどう書いていいかわからず・・・。
もしくは、大量にselectした結果を高速にinsertできる別の方法があれば
教えていただきたいです・・・。