毎年夏がやってくる度「日本暑い〜」とぐったりしてるタイラです。
さて、前回に引き続きデータベースに関するお話で、
複数のレコードを挿入する際"一度にまとめて"挿入するとどれほど高速化されるのか
というお話です。
データベースを触りたての頃は
レコード(データ)を何件も挿入する際は1回1回クエリ(要求)を投げていた
なんて事があったかもしれませんが、
1つのクエリでまとめる事で大幅に高速化出来るのでそれを紹介したいと思います。
ちなみに、レコードを1つのクエリでまとめて挿入する事を バルクINSERT といいます。
テーブル構成は前回利用した構成を利用します。
CREATE TABLE IF NOT EXISTS `sample` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data` varchar(128) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| data | varchar(128) | NO | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | timestamp | NO | | CURRENT_TIMESTAMP | |
+------------+--------------+------+-----+-------------------+----------------+
まずは比較の為の1件INSERTするクエリ
10件必要な場合は以下のクエリを10回実行します。
INSERT INTO `sample`
(`data`, `created_at`)
VALUES
('サンプル', NOW());
次に10件をバルクINSERTするクエリ
カンマ(,)区切りで書いていく事で1回のクエリで
まとめて10件、100件、1000件とまとめてINSERT出来ます。
※100件1000件といったクエリは長いので割愛しますね
INSERT INTO `sample`
(`data`, `created_at`)
VALUES
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW()),
('サンプル', NOW());
それぞれのクエリを手元のサーバでテストしてみたところ
時間は以下の通りになりました。
+-------+----------+----------+
| N | 1件xN回 | N件x1回 |
+-------+----------+----------+
| 2 | 0.03sec | 0.01sec |
| 10 | 0.08sec | 0.02sec |
| 100 | 0.64sec | 0.05sec |
| 1000 | 6.21sec | 0.06sec |
| 10000 | 64.88sec | 0.56sec |
+-------+----------+----------+
10件ですら60ms程度の差が出ています。
万単位のレコードになると100倍以上の差に。。。
複数件INSERTする際には一度にまとめて行う方が効率的...と言いますか
まとめないという選択肢はないですよね
INSERTクエリを投げる際には気をつけてください。
それでは

