Elasticsearch-hadoopをもうちょい調べて遅い理由が少しわかった
■これまでの話
第4回Elasticsearch勉強会でElasticsearch-hadoopについて発表させて頂きましたが、その際、評価としてHiveの実行速度をHDFSをストレージとして利用した場合と比較してお見せしました。
ここらへんです。
で、ちょっといくらなんでも遅すぎるな、と思って調べていたらわかったことがあったのでメモ。
■わかったこと
結論から言うと、elasticsearch-hadoopはRead時はPrimary Shardの数しかMapタスクを生成しない。
これはelasticsearch-hadoopのここら辺のソースを読んでもわかります。
・EsInputFormat.java getSplitsメソッド
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Hadoopは利用するInputFormatのgetSplitsメソッドの返り値の長さで、Mapタスク数を決定します。
このソースを見るとわかるように、Shardのsizeで配列を生成してますね。。
#Hive利用時に実際に利用するInputFormatはEsHiveInputFormatなのですが、EsHiveInputFormatのgetSplitsが内部で上記を呼び出しています。
しかし、そもそもちゃんと公式ホームページ見てみると、elasticsearch-hadoopのトップページに書いてありましたw
■じゃあ、どうすればいいのか
とりあえずは、インデックス生成の際にShardの数を多くすれば解決します。
しかし、ElasticsearchはShardの数をインデックス生成後は変更できない(はず)なので、微妙な感が否めませんが。。。
もっといい方法はないだろうか。。。
次回のElasticearch勉強会でMapRの@nagixさんから聞けたりするといいな。
■追試
前回の評価では、シャード数が6なので、6つのMapタスクしか生成されてないことになります。 実際、ログを確認したところ、生成されたMapタスク数は6でした。
一方、HDFSを利用した場合はMapタスクは12個生成されていました。
TaskTrackerは3台ともmapred.tasktracker.map.tasks.maximumを4に設定しているので、最大で12Mapを並列実行可能です。
また、サーバは4コアマシンですので、CPU的にも3台合わせて12Mapを並列実行できる計算になります。
#実際にはElasticseachとかのプロセスがCPUリソースを消費しますが
よって、HDFS利用時は12コアを使用し、elasticsearch-hadoop利用時は6コアしか使用されていないことになります。
Oh,,,ということで再度評価を行いました。
TaskTrackerとElasticsearchが同居したサーバを3台用意し(上記スライドの3番目の評価環境と同じ)、シャード数を12、レプリカ数を2でインデックスを生成して実行しました。
結果は520ms ➡ 280ms前後にまで短縮できました。
HDFS利用時の速度とはまだまだ差はありますが、少しはマシになりました。。
#そもそも1分でも十分遅いので、1分も5分もそんなに大して変わらないとかなんとか
■お詫びと訂正
スライドの10ページ目で「ドキュメント1件で1Mapタスク」とありますが、正しくはMapReduceでreadする場合もHive同様、生成されるMapタスクの数はPrimary Shardの数でした。
お詫びして訂正します。
#一番最初にドキュメント数を極小で試したのですが、その時のドキュメント数とシャード数が同じだったようです。。