サーバで収集したログファイルをローカルで解析したくて、Embulkを使ってみたんですよ。
テストファイルを食わせてみたら中々良い感じに動いてくれて、出力を変更するだけでCSVとかElasticsearchに出力できて、これは(・∀・)イイ!!と、そう思ってたんですね。
で、650MBくらいの本番のファイルを食わせたら、終わらないんですよ。ちょっと休憩して戻ってきても、まだ終わってない。
入力ファイルを正規表現でパースしていたので遅いのかと思ったのですが、調べて見ると違うようで。どうも日時文字列をTimestampに変換するのが遅いみたいなんですね。issueも切られているので、有名な問題なんですかね?
なんか改善される気配が無い (JRubyの改善待ち?) ので、SimpleDateFormatで変換するFilterを作ってみました。
インストール
$ embulk gem install embulk-filter-timestamp_hs
設定
通常はParserでtypeをtimestampにしますが、timestamp_hsを使用する場合はstringとします。
stringで取り込んだ日時文字列を、Filterでtimestampに変換します。このとき、日時文字列のformatはRuby形式では無く、SimpleDateFormat形式としてください。
in:
type: file
path_prefix: applog
parser:
type: csv
delimiter: ","
columns:
- {name: standardTimestamp, type: timestamp, format: '%Y-%m-%d %H:%M:%S.%L'}
- {name: highSpeedTimestamp, type: string}
filters:
- type: timestamp_hs
default_timezone: 'UTC'
column_options:
highSpeedTimestamp: {format: 'yyyy-MM-dd hh:mm:ss.SSS'}
実行
入力ファイルを作成して、embulk previewで確認してみます。
2016-01-01 10:02:30.100,2016-01-01 10:02:30.111
2016-01-02 10:02:30.200,2016-01-02 10:02:30.211
2016-01-03 10:02:30.300,2016-01-03 10:02:30.311
2016-01-04 10:02:30.400,2016-01-04 10:02:30.411
2016-01-05 10:02:30.500,2016-01-05 10:02:30.511
$ embulk preview config.yml
+-----------------------------+------------------------------+
| standardTimestamp:timestamp | highSpeedTimestamp:timestamp |
+-----------------------------+------------------------------+
| 2016-01-01 10:02:30.100 UTC | 2016-01-01 10:02:30.111 UTC |
| 2016-01-02 10:02:30.200 UTC | 2016-01-02 10:02:30.211 UTC |
| 2016-01-03 10:02:30.300 UTC | 2016-01-03 10:02:30.311 UTC |
| 2016-01-04 10:02:30.400 UTC | 2016-01-04 10:02:30.411 UTC |
| 2016-01-05 10:02:30.500 UTC | 2016-01-05 10:02:30.511 UTC |
+-----------------------------+------------------------------+
性能
日時文字列だけで100万行のファイルを処理して、処理時間を比較してみました。
- OS: Windows 10
- CPU: Core i5 2.67GHz
- Embulk: 0.8.6
Embulk標準: 240.910秒
timestamp_sh: 1.902秒
ちゃんと早くなってます。
Embulkが改善されたら不要となりますが、それまでは、これでなんとかなりそうです。