大規模CSVをMySQLに入れる

9,309 views

Published on

0 Comments
14 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,309
On SlideShare
0
From Embeds
0
Number of Embeds
44
Actions
Shares
0
Downloads
13
Comments
0
Likes
14
Embeds 0
No embeds

No notes for slide

大規模CSVをMySQLに入れる

  1. 1. 大規模 CSV を MySQL に入れる 飯塚修平
  2. 2. この発表の目的• ログデータ数年分を MySQL (RDS) に入れる。 – 30万レコード/(日・テーブル) * 365 日/年 * 3 年 * 5 テーブル = 16 億レコードくらいの規模 – とりあえず 1 年分だけでも入れたい・・・• 今回の苦悩を紹介することで、今後同じようなタスクに 取り組む人の参考にしてもらう。• さらに良い方法があればぜひ紹介してください。
  3. 3. まず• BULK INSERT で書いた – ウェブアプリで API のレスポンスを格納する時にはよく使う • Facebook の友人リストとか, 某の ID リストとか – INSERT INTO tbl VALUES (val,val,val), (val,val,val), (val ...• 遅すぎ。
  4. 4. ので• LOAD DATA INFILE で書いた – はやい! – 基本的に • “” あり→ VARCHAR, TEXT • “” なし→ INT, FLOAT – しかし、上手くやれば DATETIME 型に対応したり、文字列処理 しながら入れることも可能
  5. 5. たとえば• こんな 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/
  6. 6. ならばこんなかんじLOAD DATA LOCAL INFILE „hoge.csv‟ # RDS の場合 LOCAL が必要REPLACE INTO TABLE tbl # REPLACE か IGNORECHARACTER SET utf8FIELDS 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
  7. 7. 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
  8. 8. 高速化のために• 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
  9. 9. RDS のインスタンスと書き込み速度 small medium
  10. 10. まとめ• 基本的に InnoDB。しかし、書き込みをしない、全文検 索したいなど、特別な状況では MyISAM を検討しても よい。• LOAD DATA INFILE 構文のオプションを使いこなせば、 大抵のことはできる。• 無駄なく適切なデータ型でスキームを書くべし。• 高速化のためには EXPLAIN でチューニングを行うべ し。

×