RDSにデータを高速にインポートしたい。LOAD DATA LOCAL INFILEが動くのか試していた。
MySQL DB インスタンスからのデータのインポートおよびエクスポート - Amazon Relational Database Service
ドキュメントによると、LOAD DATA LOCAL INFILEは使えるらしい。
EC2にUbuntuのインスタンスを作成し、EC2からRDSのMySQLに対してデータを投入してみた。
確認したバージョンは、Ubuntu 14.04, MySQL 5.6。EC2とRDSのインスタンスの種類は共にm3.medium。
準備
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install mysql-client-5.6
対象のデータベーステーブルのDDL
ID値、文字列、数値を格納できる単純なテーブルの定義です。
CREATE TABLE `mytable` ( `id` INTEGER(10) NOT NULL auto_increment, `value1` VARCHAR(37) NOT NULL, `value2` INTEGER(4) NOT NULL, PRIMARY KEY(id) );
この定義でテーブルを作っておきます。
インデックスがある場合は削除してからロードしたほうがいいかもしれない。
読み込ませるデータ
Pythonスクリプトを書いて読み込ませるTSV形式のデータを生成しました。
# make_data.py import sys import uuid import random def main(): id_ = 0 while True: id_ += 1 if id_ > 15000000: break value1 = uuid.uuid4() value2 = random.randrange(1000) sys.stdout.write("{}\t{}\t{}\n".format(id_, value1, value2)) if __name__ == '__main__': main()
$ python make_data.py > input.tsv $ ls -lh input.tsv -rw-rw-r-- 1 ubuntu ubuntu 704M Sep 15 15:47 input.tsv
ファイルサイズは700MB程度。
ロードする
EC2のインスタンスからMySQLクライアントでRDSに接続し、LOAD DATA LOCAL INFILEクエリを投げてみます。
Ubuntuなのでapparmorがデフォルトで有効になっていますが、あらかじめ停止しています。
LOAD DATA LOCAL INFILE '/home/ubuntu/input.tsv' INTO TABLE mytable FIELDS TERMINATED BY '\t';
RDSに接続して実行してみます。
$ mysql -u myuser -h testdb.csyajfcwd1d7.ap-northeast-1.rds.amazonaws.com -D test -p Enter password: Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 35 Server version: 5.6.23 MySQL Community Server (GPL) Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> LOAD DATA LOCAL INFILE '/home/ubuntu/input.tsv' -> INTO TABLE mytable -> FIELDS TERMINATED BY '\t'; Query OK, 15000000 rows affected (2 min 35.12 sec) Records: 15000000 Deleted: 0 Skipped: 0 Warnings: 0
2分半程度で1500万件のインポートが完了しました。
データの確認
mysql> SELECT COUNT(*) FROM mytable; +----------+ | COUNT(*) | +----------+ | 15000000 | +----------+ 1 row in set (4.65 sec) mysql> SELECT * FROM mytable LIMIT 5; +----+--------------------------------------+--------+ | id | value1 | value2 | +----+--------------------------------------+--------+ | 1 | c3334206-8b02-4860-a939-c42c2df07978 | 88 | | 2 | 8affc52f-e499-4225-9ae0-0cdddb094106 | 285 | | 3 | dea4d9c8-2c4f-45ed-b517-11e768ae9bc2 | 51 | | 4 | 7e751411-18d5-4413-8bf7-da479ca91c0a | 458 | | 5 | 9afda3cb-6c50-4dd8-b0a7-c4e410deb6f3 | 130 | +----+--------------------------------------+--------+ 5 rows in set (0.00 sec)
問題なさそうでした。