![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
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を高速化させたい
その他(データベース)
-
数百万件レコードのdelete
SQL Server
-
oracleのinsert select性能
Oracle
-
-
4
SQLServer Insertが遅い
SQL Server
-
5
トランザクションログを出力せずにデータを削除する方法
Oracle
-
6
ACCESSで一括処理する方法
その他(データベース)
-
7
SQLの速度をあげるには・・・
Visual Basic(VBA)
-
8
group byの並び順を変えるだけで結果が異なる
Oracle
-
9
(SQLSERVER) 別サーバーへテーブルコピー
SQL Server
-
10
[Access] パススルークエリーで実行すると遅い
Access(アクセス)
-
11
ストアドプロシージャ_カーソルのヒット件数
その他(データベース)
-
12
バッチファイルのコピーで
その他(プログラミング・Web制作)
-
13
Viewにインデックスは張れますか?
Oracle
-
14
T-SQLで任意の箇所で強制終了する方法
SQL Server
-
15
「済」の反対語は?
日本語
-
16
DataTableに入っているデータを全てinsertしたい!(C#)
Microsoft ASP
-
17
INSERTできるレコード数を制限する。
PostgreSQL
-
18
オラクルではできるのにSQLSERVERではサブクエリーで複数キーを指定できない?
SQL Server
-
19
SQLPLUSで結果を画面に表示しない
Oracle
-
20
検索結果の列数を動的に変更したい
SQL Server
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
SQL Left Join で重複を排除す...
-
VIEWの元のテーブルのindexって...
-
入力値と外部キーをINSERTするには
-
SQLサーバから、項目の属性(型...
-
select文のwhere句に配列を入れ...
-
inner joinをすると数がおかし...
-
MySQLのDATE型カラム値がNULLの...
-
ある条件の最大値+1を初番する...
-
クエリ表示と、ADOで抽出したレ...
-
同一のユーザー、同一商品のと...
-
複数のUPDATE文の実行
-
全角文字を含む行を検索
-
Updateの複数テーブル条件時のL...
-
エクセルの関数について教えて...
-
テーブル作成です。どこかのス...
-
php+mysqlで複数選択削除について
-
MySQLのint型で001と表示する方...
-
別のDB(Table)からの複数行の...
-
書籍の内容はまともでしょうか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
副問合せの書き方について
-
SQLサーバから、項目の属性(型...
-
SQL Left Join で重複を排除す...
-
select文のwhere句に配列を入れ...
-
VIEWの元のテーブルのindexって...
-
PL/SQLの変数について
-
マイクラPC版のコマンドで効率...
-
エクセルの関数について教えて...
-
SQLにて特定の文字を除いた検索...
-
sqlで、600行あるテーブルを100...
-
Access パラメータクエリをcsv...
-
Unionした最後にGROUP BYを追加...
-
inner joinをすると数がおかし...
-
複数テーブルのGROUP BY の使い...
-
ある条件の最大値+1を初番する...
-
MySQLのint型で001と表示する方...
-
クエリ表示と、ADOで抽出したレ...
-
[MySQL] UNIQUE制約の値を更新...
-
テーブル名を省略して「h.id」...
おすすめ情報
回答ありがとうございます。
プロシージャ内で、大量データをselectして
数件ずつバルクinsertしたいのですがどう書いていいかわからず・・・。
もしくは、大量にselectした結果を高速にinsertできる別の方法があれば
教えていただきたいです・・・。