概要
Amazon Elasticsearch Service(以下 Amazon ES)で Indexing のパフォーマンスチューニングを行い、
約3倍の改善が見られたのでそのときやったことで効果が高かったこと、逆に低かったことなどを書きます。
前提
チューニング対象の index はウェブサービスなどにおける検索用途のもので、
日時で index を作り直し alias を切り替える運用であるため、
primary shard の調整や Mappings の変更が比較的容易にできる前提です。
計測方法
CloudWatch Metrics の IndexingLatency
や IndexingRate
で計測します。
- IndexingLatency : インデックス作成オペレーションを完了するためにシャードで必要な平均時間(ミリ秒)
- IndexingRate : 1分あたりのインデックス作成オペレーションの数
効果があったチューニング
基本的に Elastic 社や AWS 社のドキュメントに書かれていることを行っています。
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html
https://aws.amazon.com/jp/premiumsupport/knowledge-center/elasticsearch-indexing-performance/
使用していない Field の削除
使用していない Field を Mappings から削除します。
特にコストが高い text を削除すると効果が高いはずです。
このチューニングにより IndexingLatency
が2倍改善しました。
インスタンスタイプの変更
専用マスターノードもデータノードも t3 インスタンスをしていましたが、
これは本番用のインスタンスではないため、専用マスターノードを c6g 、データノードを r6g に変更しました。
専用マスターノードはコンピューティング最適化の c6g などを選び、
データノードは汎用もしくはメモリ最適化の m6g, r6g などを選ぶと良いです。
https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/sizing-domains.html#aes-bp-instances
Shard 数の最適化
実際に入っているデータの容量からサイジングを再度行い、ノード数と Primary Shards を減らしました。
https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/sizing-domains.html
公式ではシャード数に関して多すぎるよりは少なすぎる方が良いとあります。
bulk size の調整
Elastic 社のドキュメントにあるように徐々に Bulk API の bulk size を上げていき限界値を探ります。
筆者の場合はだいたい 20MB 程度でパフォーマンスが頭打ちになりました。
上記の4つのチューニングが特に効果が高く、ほかは若干改善したかな程度でした。
refresh_interval の延長
refresh_interval を 60s に引き上げました。若干 IndexingRate
が改善しました。
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html#_unset_or_increase_the_refresh_interval
Auto-Tune
https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/auto-tune.html
導入中のステータスで検証は十分ではありませんが、
Amazon ES のみの機能として Auto-Tune があり、thread pool を自動で最適化することで、
indexing 時の429エラーを回避しやすくなりそうです。
効果がなかったチューニング
ローカルストレージの使用
Elastic 社のドキュメントでは EBS などの Virtualized storage は遅いと指摘があるため、
r6g を NVMe SSD の r6gd に変更してみました。
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html#_use_faster_hardware
が、こちらはほぼパフォーマンスに影響はなかったため r6g にもどしました。
レスポンスサイズの削減
Elasticsearch への書き込みは embulk-output-elasticsearch を用いていますが、
以下の箇所に修正を入れ bulk のレスポンスで items のフィールドを除外しました。
https://github.com/embulk/embulk-output-elasticsearch/blob/99e1ee36ea2adf0c0e925f9d4f0ad953a1e44b01/src/main/java/org/embulk/output/elasticsearch/ElasticsearchHttpClient.java#L86
が、indexing のパフォーマンスはほぼ変わりませんでした。
もちろん帯域幅の使用率などには効果があるため、転送速度は向上していると考えられます。
やらなかったチューニング
number_of_replicas を0に設定
number_of_replicas を0に設定しましたが、特に改善していなさそうだったのと、
indexing 中は number_of_replicas を0にし、indexing 完了後に戻す必要がありますが、
workflow が複雑になるため採用しませんでした。
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html#_disable_replicas_for_initial_loads
auto-generated ids の使用
Bulk 時に _id フィールドを使用しないことで auto-generated ids で id が振られ、
シャードを検索するコストが削減されますが、古い Elasticsearch では効果があるが今は十分に高速化されているのと、
Update がしづらくなることから採用しませんでした。
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html#_use_auto_generated_ids
_source, _all の disable
よく indexing に効くチューニングとして紹介されていますが、
Elastic 社のドキュメントでは enable によるメリットの方が大きいと書かれています。
安易に disable にしない方が良いでしょう。
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html