
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で質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
insertを高速化させたい
その他(データベース)
-
oracleのinsert select性能
Oracle
-
ACCESSで一括処理する方法
その他(データベース)
-
-
4
SQLServer Insertが遅い
SQL Server
-
5
テーブルに主キーを作らないデメリットは?
その他(Microsoft Office)
-
6
Dosブロンプトでtabを出力したい
その他(プログラミング・Web制作)
-
7
Viewにインデックスは張れますか?
Oracle
-
8
ORA-01013のエラーについて経験のある方お願いします。
Oracle
-
9
ROWNUMでUPDATEをしたいのですが・・・。
Oracle
-
10
selectした結果の余計な余白を取るにはどうしたらよいのでしょうか
Oracle
-
11
select insertで複数テーブルから値を取得したい
Oracle
-
12
データを削除しても表領域の使用率が減りません
Oracle
-
13
sqlで、600行あるテーブルを100行毎に分けてcsvファイルに書き出す方法を教えてください。
SQL Server
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルの関数について教えて...
-
SQL Left Join で重複を排除す...
-
マイクラPC版のコマンドで効率...
-
updateを1行ずつ実行したい。
-
selectで拾ってきたデータをも...
-
埼玉県の中央部の方!!
-
inner joinをすると数がおかし...
-
ローカルルーターモードとは
-
DB設計について
-
エクセルで最後の文字だけ置き...
-
イケメンにチーズバーガーをぶ...
-
MySQLで半角濁音文字の検索
-
入力値と外部キーをINSERTするには
-
URL と行番号の指定
-
Access VBAでのIDの自動発番
-
SQLの検索について
-
Mysql UPDATE出来ません
-
差し込み後、元データを変更し...
-
列番号による項目の取得について
-
noの後の語
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
エクセルの関数について教えて...
-
VIEWの元のテーブルのindexって...
-
エラー 1068 (42000): 複数の主...
-
SQLサーバから、項目の属性(型...
-
select文のwhere句に配列を入れ...
-
SQL Left Join で重複を排除す...
-
Access パラメータクエリをcsv...
-
マイクラPC版のコマンドで効率...
-
【Transact-sql】 execの結果を...
-
sqlで、600行あるテーブルを100...
-
SQLにて特定の文字を除いた検索...
-
1テーブル&複数レコードの更新...
-
PL/SQLの変数について
-
WordpressのContact form 7でzi...
-
複数テーブルのGROUP BY の使い...
-
バインド変数について
-
inner joinをすると数がおかし...
-
MySQLのint型で001と表示する方...
-
updateを1行ずつ実行したい。
おすすめ情報
回答ありがとうございます。
プロシージャ内で、大量データをselectして
数件ずつバルクinsertしたいのですがどう書いていいかわからず・・・。
もしくは、大量にselectした結果を高速にinsertできる別の方法があれば
教えていただきたいです・・・。