Elasticsearch 2.0のインデキシングのパフォーマンスに関する考慮事項

1年とすこし前、私はElasticsearchでインデキシングのスループットを最大化する方法を説明しました。あれから多くの変更がありました。そこで、Elasticsearch 2.0.0のインデキシングのパフォーマンスに影響を与える変更についてあらためて説明したいと思います。

制限の保存を自動化

2.0.0より前のElasticsearchでは、進行中のマージを一定の割合(デフォルトで20 MB/秒)に制限していました。しかし、これは低すぎる場合も多く、マージが遅れ、それ以降のインデキシングが制限されることがよくありました。

Elasticsearch 2.0.0では、適応型のマージIO制限を使用するようになりました。マージが遅れ始めると許容されるIO率が高くなり、マージが追いつくと低くなります。つまり、突発的に大きなマージがスループットの低いインデキシングで発生したとしてもノードで使用可能なすべてのIOが枯渇せず、進行中の検索やインデキシングに与える影響を最小限に抑えることができます。

ただし、大量のインデキシングが実行中の場合は、許容されるマージIOもそれに応じて高くなります。

これは良いことです。制限設定に手を加えることなく、ただデフォルトを使用すれば良いのですから。

複数のpath.data

複数のIOデバイスを使用(複数のpath.dataパスを指定)したノードでのシャードの保持は、ストレージの合計容量が増えた場合に便利であり、IOのパフォーマンスがボトルネックとなるようなElasticsearchの使い方をしている場合、IOのパフォーマンスが向上します。

Elasticsearchによる複数のパスでのIOの負荷分散には重要な変更があります。以前は、それぞれの低レベルのインデックスファイルを最適な(デフォルトでは、最も空いている)パスに送信していましたが、現在ではその基準がシャードごとになりました。シャードがノードに割り当てられると、ノードはどのパスがそのシャードのすべてのファイルを保持するかを選択します。

IOデバイスの障害に対する耐障害性の向上:IOデバイスのいずれかがクラッシュした場合、現在ではそのデバイス上のシャードが失われるだけですが、2.0.0より前は、影響を受けるデバイスに1つ以上のファイルがあるシャードがすべて失われていました(通常、これはそのノードのほぼすべてのシャードとなります)。

OSレベルのRAID 0デバイスも、いずれかのデバイスで障害が発生すると、そのノードのすべてのシャードが失われるため、あまり良い選択肢とは言えません。ですから、複数のpath.dataを使用することを推奨します。

また、インデックスのレプリカを少なくとも1つ保持して、失われたシャードを復旧できるようにしてデータの消失を防ぐ必要があります。

自動ID最適化の廃止

これまで、Elasticsearchは、自動的にIDを付与するケース(インデックスされる各ドキュメントに独自のIDを指定しなかった場合)において、内部で追記専用のLucene APIを使用することで最適化していましたが、この方法では問題が発生してエラーが起こることがわかり、廃止しました

また、IDルックアップのパフォーマンスも大幅に向上したため、この最適化はそれほど重要ではなくなり、これによって完全にブルームフィルタを廃止できました。ブルームフィルタは膨大なヒープを消費する割りには、IDルックアップのパフォーマンス向上につながらなかったためです。

また、1.4.0では、Elasticsearchは以前のUUIDに対してのルックアップのパフォーマンスを向上させるために、Flake IDを使用してIDを生成するようになっています。

自動IDの処理が廃止されたことで、パフォーマンスを犠牲にすることなく、独自のIDフィールドを自由に使用できるようになりました。ただし、IDフィールド値の選択によってインデキシングのパフォーマンスに影響するので注意が必要です。

その他のインデキシングに関する変更

こうした変更以外にも、2.0のインデキシングでは以下のような大きな変更が多数あります。(検索時にCPUやヒープを大きく消費するfielddataを使用するのではなく)デフォルトでのdoc valuesの有効化、危険なdelete-by-query APIをコアAPIからバルクインデキシングAPIを使用する安全なプラグインへの移動、インデキシング中のstoredフィールドの圧縮率の増加に対する制御の実現、少数のdoc valuesおよびnormsの圧縮の改善、マージ時に必要なヒープの削減、マージ時に以前から存在していたインデックス破損の検出などの耐障害性の大幅な向上。

インデキシング中の低レベルでのLuceneアクションに興味があるなら、code>index.engine.lucene.iw: TRACEをlogging.ymlに追加してみてください。ただし、出力が膨大になるので注意してください。

Elasticsearchの毎晩のインデキシングパフォーマンスのチャートを見れば、デフォルト設定が正しい改善であることが分かります。デフォルト(4GB)ヒープのdocs/秒とセグメント数は、高速なパフォーマンスラインに追いついています。