大規模csvをmysqlに入れる

10
大大大 CSV 大 MySQL 大大大大 大大大大

Upload: shuhei-iitsuka

Post on 19-Jun-2015

5.305 views

Category:

Documents


7 download

TRANSCRIPT

Page 1: 大規模CSVをMySQLに入れる

大規模 CSV を MySQL に入れる

飯塚修平

Page 2: 大規模CSVをMySQLに入れる

この発表の目的• ログデータ数年分を MySQL (RDS) に入れる。

– 30 万レコード /( 日・テーブル ) * 365 日 / 年 * 3 年 * 5 テーブル = 16 億レコードくらいの規模

– とりあえず 1 年分だけでも入れたい・・・

• 今回の苦悩を紹介することで、今後同じようなタスクに取り組む人の参考にしてもらう。

• さらに良い方法があればぜひ紹介してください。

Page 3: 大規模CSVをMySQLに入れる

まず• BULK INSERT で書いた

– ウェブアプリで API のレスポンスを格納する時にはよく使う• Facebook の友人リストとか , 某の ID リストとか

– INSERT INTO tbl VALUES (val,val,val), (val,val,val), (val ...

• 遅すぎ。

Page 4: 大規模CSVをMySQLに入れる

ので• LOAD DATA INFILE で書いた

– はやい!– 基本的に

• “” あり→ VARCHAR, TEXT• “” なし→ INT, FLOAT

– しかし、上手くやれば DATETIME 型に対応したり、文字列処理しながら入れることも可能

Page 5: 大規模CSVをMySQLに入れる

たとえば• こんな CSV

– “ セッション ID”, “Page”, “ タイムスタンプ” , “Page Views”– "10000339141949907327:6","1","2011/01/01 12:10:27",1

• こんな テーブル– session_id VARCHAR(100) NOT NULL– session_num INTEGER(11) NOT NULL– to_page INTEGER(11) NOT NULL– timestamp DATETIME NOT NULL– page_view INTEGER(11) NOT NULL

• ちなみに、 NOT NULL をつけていないカラムをキーにして走査するとパフォーマンスが落ちる。参考 http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/

Page 6: 大規模CSVをMySQLに入れる

ならばこんなかんじ

LOAD DATA LOCAL INFILE ‘hoge.csv’ # RDS の場合 LOCAL が必要REPLACE INTO TABLE tbl # REPLACE か IGNORE CHARACTER SET utf8 FIELDS TERMINATED BY ‘,’ # CSV なので OPTIONALLY ENCLOSED BY ‘“’ # “” 囲みなので IGNORE 1 LINES # 先頭行は無視する(@var1, to_page, @var2, page_view)SETsession_id = SUBSTRING(@var1, 1, LOCATE(':', @var1)-1), session_num = SUBSTRING(@var1, LOCATE(':', @var1)+1),timestamp = STR_TO_DATE(@var2, '%Y/%m/%d %H:%i:%s’);“10000339141949907327:6” → “10000339141949907327”, 6DATETIME の型を指定する

参考 http://kedar.nitty-witty.com/blog/load-delimited-data-csv-excel-into-mysql-server

Page 7: 大規模CSVをMySQLに入れる

InnoDB か MyISAM か• とりあえず InnoDB ?

◯ トランザクション対応• ウェブサービスでは必須

◯ 行ロック ✕ データサイズが大きい• MyISAM の 2~3 倍

✕ 構造が複雑• MyISAM を使うことに。

◯ SELECT COUNT(*) が異様に速い• InnoDB → type=INDEX, MyISAM → type=NULL• 参考 http://opendatabaselife.blogspot.jp/2009/10/myisaminnodb.html

✕ テーブルロック• バッチ、 SELECT 中心なら MyISAM がいいかも• ウェブで使うなら InnoDB

– 参考 http://nippondanji.blogspot.jp/2009/02/myisaminnodb.html

Page 8: 大規模CSVをMySQLに入れる

高速化のために• EXPLAIN をつかってチューニング

– select_type → type の順にチューニング• できるだけ SUBQUERY はつかわない

– SELECT ... WHERE IN (SELECT ...) みたいなやつ– 基本的に LEFT JOIN で書き換えられるはず– select_type = SINPLE を目指す

• 具体的なことは・・・http://nippondanji.blogspot.jp/2009/03/mysql_25.html

• INDEX で絞る– type = ALL( フルテーブルスキャン ) または

type = INDEX( フルインデックススキャン ) は要改善。• key_len が短くなるように

– UTF-8 の場合、 “ 123” は 9, 123 は 3

参考 http://nippondanji.blogspot.jp/2009/03/mysqlexplain.html

Page 9: 大規模CSVをMySQLに入れる

RDS のインスタンスと書き込み速度

small medium

Page 10: 大規模CSVをMySQLに入れる

まとめ• 基本的に InnoDB 。しかし、書き込みをしない、全文

検索したいなど、特別な状況では MyISAM を検討してもよい。

• LOAD DATA INFILE 構文のオプションを使いこなせば、大抵のことはできる。

• 無駄なく適切なデータ型でスキームを書くべし。

• 高速化のためには EXPLAIN でチューニングを行うべし。