シャードのサイズ設定

Elasticsearchの各インデックスは1つ以上のシャードに分割されており、各シャードはハードウェアの故障から保護するために複数のノードに複製される場合があります。データストリームを使用している場合、各データストリームは一連のインデックスによってサポートされます。単一のノードに保存できるデータの量には制限があるため、ノードを追加し、インデックスとシャードの数を増やしてクラスターの容量を増やすことができます。ただし、各インデックスとシャードにはオーバーヘッドがあり、データをあまりにも多くのシャードに分割すると、オーバーヘッドが圧倒的になる可能性があります。インデックスやシャードが多すぎるクラスターはオーバーシャーディングに苦しんでいると言われます。オーバーシャーディングされたクラスターは、検索に応答する効率が低下し、極端な場合には不安定になることさえあります。

シャーディング戦略の作成

オーバーシャーディングやその他のシャード関連の問題を防ぐ最良の方法は、シャーディング戦略を作成することです。シャーディング戦略は、クラスターに最適なシャード数を決定し維持しながら、それらのシャードのサイズを制限するのに役立ちます。

残念ながら、すべての環境に適したシャーディング戦略はありません。ある環境で機能する戦略が別の環境ではスケールしない場合があります。良いシャーディング戦略は、インフラストラクチャ、ユースケース、およびパフォーマンスの期待を考慮する必要があります。

シャーディング戦略を作成する最良の方法は、実際のハードウェア上で本番データをベンチマークし、本番で見られるのと同じクエリとインデックス負荷を使用することです。推奨される方法論については、定量的クラスターサイズ設定ビデオを参照してください。異なるシャード構成をテストする際は、KibanaのElasticsearch監視ツールを使用して、クラスターの安定性とパフォーマンスを追跡してください。

Elasticsearchノードのパフォーマンスは、しばしば基盤となるストレージのパフォーマンスによって制限されます。インデックス作成および検索のためのストレージ最適化に関する推奨事項を確認してください。

以下のセクションでは、シャーディング戦略を設計する際に考慮すべきリマインダーとガイドラインを提供します。クラスターがすでにオーバーシャーディングされている場合は、クラスターのシャード数を減らすを参照してください。

サイズ設定の考慮事項

シャーディング戦略を構築する際に、以下の点を考慮してください。

シャードごとに単一スレッドで実行される検索

ほとんどの検索は複数のシャードにヒットします。各シャードは単一のCPUスレッドで検索を実行します。シャードは複数の同時検索を実行できますが、大量のシャードにまたがる検索はノードの検索スレッドプールを枯渇させる可能性があります。これにより、スループットが低下し、検索速度が遅くなることがあります。

各インデックス、シャード、セグメント、およびフィールドにはオーバーヘッドがあります

すべてのインデックスとすべてのシャードは、いくつかのメモリとCPUリソースを必要とします。ほとんどの場合、小さなセットの大きなシャードは、多くの小さなシャードよりも少ないリソースを使用します。

セグメントは、シャードのリソース使用に大きな役割を果たします。ほとんどのシャードには、インデックスデータを保存するいくつかのセグメントが含まれています。Elasticsearchは、検索のために迅速に取得できるように、いくつかのセグメントメタデータをヒープメモリに保持します。シャードが成長すると、そのセグメントはマージされて、より少ない大きなセグメントになります。これにより、セグメントの数が減少し、ヒープメモリに保持されるメタデータが少なくなります。

マッピングされた各フィールドも、メモリ使用量とディスクスペースの観点でいくつかのオーバーヘッドを持ちます。デフォルトでは、Elasticsearchはインデックスする各ドキュメントのすべてのフィールドに対して自動的にマッピングを作成しますが、この動作をオフにしてマッピングを制御することができます。

さらに、各セグメントは、マッピングされたフィールドごとに少量のヒープメモリを必要とします。このセグメントごとのフィールドのヒープオーバーヘッドには、フィールド名のコピーが含まれ、適用可能な場合はISO-8859-1でエンコードされ、そうでない場合はUTF-16でエンコードされます。通常、これは目立ちませんが、シャードに高いセグメント数があり、対応するマッピングに高いフィールド数や非常に長いフィールド名が含まれている場合は、このオーバーヘッドを考慮する必要があります。

Elasticsearchはデータティア内でシャードを自動的にバランスします

クラスターのノードはdata tiersにグループ化されます。各ティア内で、Elasticsearchはインデックスのシャードをできるだけ多くのノードに分散させようとします。新しいノードを追加したり、ノードが失敗した場合、Elasticsearchは自動的にインデックスのシャードをティアの残りのノードに再バランスします。

ベストプラクティス

該当する場合は、以下のベストプラクティスをシャーディング戦略の出発点として使用してください。

ドキュメントではなくインデックスを削除する

削除されたドキュメントは、Elasticsearchのファイルシステムから即座に削除されるわけではありません。代わりに、Elasticsearchは各関連シャードでドキュメントを削除済みとしてマークします。マークされたドキュメントは、定期的なセグメントマージ中に削除されるまでリソースを使用し続けます。

可能な場合は、代わりにインデックス全体を削除してください。Elasticsearchは、削除されたインデックスをファイルシステムから即座に削除し、リソースを解放できます。

時系列データにデータストリームとILMを使用する

データストリームを使用すると、時間ベースのバックインデックスにわたって時系列データを保存できます。インデックスライフサイクル管理(ILM)を使用して、これらのバックインデックスを自動的に管理できます。

このセットアップの利点の1つは、自動ロールオーバーで、現在のインデックスが定義されたmax_primary_shard_sizemax_agemax_docs、またはmax_sizeの閾値に達すると、新しい書き込みインデックスが作成されます。インデックスがもはや必要ない場合、ILMを使用して自動的に削除し、リソースを解放できます。

ILMは、時間の経過とともにシャーディング戦略を変更するのも簡単にします:

  • 新しいインデックスのシャード数を減らしたいですか?
    データストリームの一致するインデックステンプレートindex.number_of_shards設定を変更します。
  • より大きなシャードまたはより少ないバックインデックスが必要ですか?
    ILMポリシーのロールオーバー閾値を増やします。
  • 短い間隔を跨ぐインデックスが必要ですか?
    古いインデックスを早く削除することで、増加したシャード数を相殺します。これは、ポリシーの削除フェーズmin_age閾値を下げることで実行できます。

新しいバックインデックスは、戦略をさらに調整する機会です。

200Mドキュメントまでのシャード、または10GBから50GBのサイズを目指す

各シャードには、クラスター管理と検索パフォーマンスの両方に関連するオーバーヘッドがあります。1000の50MBシャードを検索することは、同じデータを含む1つの50GBシャードを検索するよりもはるかに高価になります。ただし、非常に大きなシャードは、検索を遅くし、障害からの回復に時間がかかる可能性もあります。

シャードの物理的なサイズに関する厳密な制限はなく、理論的には各シャードは20億ドキュメントを超えることができます。ただし、経験則として、シャードのドキュメント数が200百万未満に保たれている限り、10GBから50GBの間のシャードが多くのユースケースでうまく機能します。

ネットワークやユースケースによっては、より大きなシャードを使用できる場合があり、エンタープライズ検索や同様のユースケースには小さなシャードが適している場合があります。

ILMを使用している場合は、ロールオーバーアクションmax_primary_shard_size閾値を50gbに設定して、50GBを超えるシャードを避けてください。

シャードの現在のサイズを確認するには、cat shards APIを使用します。

Python

  1. resp = client.cat.shards(
  2. v=True,
  3. h="index,prirep,shard,store",
  4. s="prirep,store",
  5. bytes="gb",
  6. )
  7. print(resp)

Ruby

  1. response = client.cat.shards(
  2. v: true,
  3. h: 'index,prirep,shard,store',
  4. s: 'prirep,store',
  5. bytes: 'gb'
  6. )
  7. puts response

Js

  1. const response = await client.cat.shards({
  2. v: "true",
  3. h: "index,prirep,shard,store",
  4. s: "prirep,store",
  5. bytes: "gb",
  6. });
  7. console.log(response);

Console

  1. GET _cat/shards?v=true&h=index,prirep,shard,store&s=prirep,store&bytes=gb
  1. #### Txt
  2. ``````txt
  3. index prirep shard store
  4. .ds-my-data-stream-2099.05.06-000001 p 0 50gb
  5. ...
  6. `

インデックスのシャードが推奨される50GBサイズを超えてパフォーマンスが低下している場合、インデックスのシャードサイズを修正することを検討してください。シャードは不変であり、そのサイズは固定されているため、インデックスは修正された設定でコピーする必要があります。これには、データをコピーするための十分なディスクを確保することが必要です。その後、以下のいずれかのオプションを使用して、修正された設定でインデックスのデータをコピーできます:

  • Split Indexを実行してプライマリシャードの数を増やす
  • 修正された設定で宛先インデックスを作成し、次にReindexを実行する

Restore SnapshotClone Indexを実行しても、シャードのサイズを解決するには不十分です。

ソースインデックスのデータが宛先インデックスにコピーされたら、ソースインデックスを削除できます。その後、ソースインデックスの名前を指すために、宛先インデックスにCreate Aliasを設定することを検討できます。

マスター候補ノードは、3000インデックスごとに少なくとも1GBのヒープを持つべきです

マスターノードが管理できるインデックスの数は、そのヒープサイズに比例します。各インデックスに必要なヒープメモリの正確な量は、マッピングのサイズやインデックスごとのシャード数など、さまざまな要因によって異なります。

一般的な目安として、マスターノードの1GBのヒープあたり3000インデックス未満であるべきです。たとえば、クラスターに4GBのヒープを持つ専用のマスターノードがある場合、12000インデックス未満であるべきです。マスターノードが専用でない場合でも、同じサイズガイダンスが適用されます:クラスター内の3000インデックスごとに、各マスター候補ノードに少なくとも1GBのヒープを確保する必要があります。

このルールは、マスターノードが管理できるインデックスの絶対的な最大数を定義しますが、この数のインデックスを含む検索やインデックス作成のパフォーマンスを保証するものではありません。また、データノードがワークロードに対して十分なリソースを持っていること、全体のシャーディング戦略がすべてのパフォーマンス要件を満たしていることを確認する必要があります。シャードごとに単一スレッドで実行される検索各インデックス、シャード、セグメント、およびフィールドにはオーバーヘッドがありますも参照してください。

各ノードのヒープの設定サイズを確認するには、cat nodes APIを使用します。

Python

  1. resp = client.cat.nodes(
  2. v=True,
  3. h="heap.max",
  4. )
  5. print(resp)

Ruby

  1. response = client.cat.nodes(
  2. v: true,
  3. h: 'heap.max'
  4. )
  5. puts response

Js

  1. const response = await client.cat.nodes({
  2. v: "true",
  3. h: "heap.max",
  4. });
  5. console.log(response);

Console

  1. GET _cat/nodes?v=true&h=heap.max

cat shards APIを使用して、ノードごとのシャード数を確認できます。

Python

  1. resp = client.cat.shards(
  2. v=True,
  3. )
  4. print(resp)

Ruby

  1. response = client.cat.shards(
  2. v: true
  3. )
  4. puts response

Js

  1. const response = await client.cat.shards({
  2. v: "true",
  3. });
  4. console.log(response);

Console

  1. GET _cat/shards?v=true

クラスターのシャード制限内に収まるように十分なノードを追加する

クラスターのシャード制限は、ノードごとに1000の非凍結シャード、専用の凍結ノードごとに3000の凍結シャードを超える作成を防ぎます。必要なシャード数を処理するために、クラスター内に各タイプの十分なノードがあることを確認してください。

フィールドマッパーとオーバーヘッドのために十分なヒープを許可する

マッピングされたフィールドは、各ノードでいくつかのヒープメモリを消費し、データノードでは追加のヒープが必要です。各ノードにマッピング用の十分なヒープがあることを確認し、ワークロードに関連するオーバーヘッドに対しても追加のスペースを確保してください。以下のセクションでは、これらのヒープ要件を決定する方法を示します。

クラスター状態のマッピングメタデータ

クラスター内の各ノードには、クラスター状態のコピーがあります。クラスター状態には、各インデックスのフィールドマッピングに関する情報が含まれています。この情報にはヒープオーバーヘッドがあります。Cluster stats APIを使用して、重複排除と圧縮後のすべてのマッピングの合計サイズのヒープオーバーヘッドを取得できます。

Python

  1. resp = client.cluster.stats(
  2. human=True,
  3. filter_path="indices.mappings.total_deduplicated_mapping_size*",
  4. )
  5. print(resp)

Ruby

  1. response = client.cluster.stats(
  2. human: true,
  3. filter_path: 'indices.mappings.total_deduplicated_mapping_size*'
  4. )
  5. puts response

Js

  1. const response = await client.cluster.stats({
  2. human: "true",
  3. filter_path: "indices.mappings.total_deduplicated_mapping_size*",
  4. });
  5. console.log(response);

Console

  1. GET _cluster/stats?human&filter_path=indices.mappings.total_deduplicated_mapping_size*

この出力例のような情報が表示されます:

Console-Result

  1. {
  2. "indices": {
  3. "mappings": {
  4. "total_deduplicated_mapping_size": "1gb",
  5. "total_deduplicated_mapping_size_in_bytes": 1073741824
  6. }
  7. }
  8. }

ヒープサイズとフィールドマッパーのオーバーヘッドを取得する

Nodes stats APIを使用して、各ノードに関連する2つのメトリックを取得できます:

  • 各ノードのヒープのサイズ。
  • 各ノードのフィールドに対する追加の推定ヒープオーバーヘッド。これはデータノードに特有であり、上記のクラスター状態フィールド情報に加えて、データノードが保持するインデックスの各マッピングされたフィールドに対する追加のヒープオーバーヘッドがあります。データノードでないノードの場合、このフィールドはゼロになる場合があります。

Python

  1. resp = client.nodes.stats(
  2. human=True,
  3. filter_path="nodes.*.name,nodes.*.indices.mappings.total_estimated_overhead*,nodes.*.jvm.mem.heap_max*",
  4. )
  5. print(resp)

Ruby

  1. response = client.nodes.stats(
  2. human: true,
  3. filter_path: 'nodes.*.name,nodes.*.indices.mappings.total_estimated_overhead*,nodes.*.jvm.mem.heap_max*'
  4. )
  5. puts response

Js

  1. const response = await client.nodes.stats({
  2. human: "true",
  3. filter_path:
  4. "nodes.*.name,nodes.*.indices.mappings.total_estimated_overhead*,nodes.*.jvm.mem.heap_max*",
  5. });
  6. console.log(response);

Console

  1. GET _nodes/stats?human&filter_path=nodes.*.name,nodes.*.indices.mappings.total_estimated_overhead*,nodes.*.jvm.mem.heap_max*

各ノードについて、次のような情報が表示されます:

Console-Result

  1. {
  2. "nodes": {
  3. "USpTGYaBSIKbgSUJR2Z9lg": {
  4. "name": "node-0",
  5. "indices": {
  6. "mappings": {
  7. "total_estimated_overhead": "1gb",
  8. "total_estimated_overhead_in_bytes": 1073741824
  9. }
  10. },
  11. "jvm": {
  12. "mem": {
  13. "heap_max": "4gb",
  14. "heap_max_in_bytes": 4294967296
  15. }
  16. }
  17. }
  18. }
  19. }

追加のヒープオーバーヘッドを考慮する

上記の2つのフィールドオーバーヘッドメトリックに加えて、Elasticsearchのベースライン使用量やインデックス作成、検索、集計などのワークロードに対して十分なヒープを許可する必要があります。多くの合理的なワークロードには0.5GBの追加ヒープが十分であり、ワークロードが非常に軽い場合はさらに少なくて済む場合がありますが、重いワークロードにはより多くのヒープが必要になる場合があります。

例として、データノードの出力を考えてみましょう。ノードのヒープは少なくとも次のように必要です:

  • クラスター状態フィールド情報のために1GB。
  • データノードのフィールドに対する追加の推定ヒープオーバーヘッドのために1GB。
  • その他のオーバーヘッドのために0.5GBの追加ヒープ。

この例では、ノードの最大ヒープサイズが4GBであるため、合計必要ヒープの2.5GBには十分です。

ノードの最大ヒープサイズが不十分な場合は、不要なフィールドを避けるか、クラスターをスケールアップするか、インデックスシャードを再分配することを検討してください。

上記のルールは、非常に多くのインデックスを含む検索やインデックス作成のパフォーマンスを必ずしも保証するものではありません。データノードがワークロードに対して十分なリソースを持っていること、全体のシャーディング戦略がすべてのパフォーマンス要件を満たしていることを確認する必要があります。シャードごとに単一スレッドで実行される検索各インデックス、シャード、セグメント、およびフィールドにはオーバーヘッドがありますも参照してください。

ノードのホットスポットを避ける

特定のノードにあまりにも多くのシャードが割り当てられると、そのノードはホットスポットになる可能性があります。たとえば、単一のノードに高いインデックスボリュームのインデックスのためにあまりにも多くのシャードが含まれている場合、そのノードは問題を抱える可能性が高いです。

ホットスポットを防ぐために、index.routing.allocation.total_shards_per_nodeインデックス設定を使用して、単一のノード上のシャード数を明示的に制限します。index.routing.allocation.total_shards_per_nodeを使用して設定できます。

Python

  1. resp = client.indices.put_settings(
  2. index="my-index-000001",
  3. settings={
  4. "index": {
  5. "routing.allocation.total_shards_per_node": 5
  6. }
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.indices.put_settings(
  2. index: 'my-index-000001',
  3. body: {
  4. index: {
  5. 'routing.allocation.total_shards_per_node' => 5
  6. }
  7. }
  8. )
  9. puts response

Js

  1. const response = await client.indices.putSettings({
  2. index: "my-index-000001",
  3. settings: {
  4. index: {
  5. "routing.allocation.total_shards_per_node": 5,
  6. },
  7. },
  8. });
  9. console.log(response);

Console

  1. PUT my-index-000001/_settings
  2. {
  3. "index" : {
  4. "routing.allocation.total_shards_per_node" : 5
  5. }
  6. }

不要なマッピングされたフィールドを避ける

デフォルトでは、Elasticsearchはインデックスする各ドキュメントのすべてのフィールドに対して自動的にマッピングを作成します。マッピングされた各フィールドは、効率的な検索、取得、および集計に必要なディスク上のデータ構造に対応します。各マッピングされたフィールドに関する詳細もメモリに保持されます。このオーバーヘッドは、フィールドが検索や集計に使用されない場合には不要な場合が多いです。動的マッピングの代わりに明示的マッピングを使用して、決して使用されないフィールドを作成しないようにします。フィールドのコレクションが通常一緒に使用される場合は、インデックス時にそれらを統合するためにcopy_toを使用することを検討してください。フィールドがめったに使用されない場合は、ランタイムフィールドにする方が良いかもしれません。

どのフィールドが使用されているかに関する情報は、フィールド使用統計APIを使用して取得でき、マッピングされたフィールドのディスク使用量をインデックスディスク使用量を分析APIを使用して分析できます。ただし、不要なマッピングされたフィールドは、ディスク使用量に加えてメモリオーバーヘッドも伴います。

クラスターのシャード数を減らす

クラスターがすでにオーバーシャーディングされている場合、シャード数を減らすために以下のいずれかの方法を使用できます。

より長い期間をカバーするインデックスを作成する

ILMを使用していて、保持ポリシーが許可する場合は、ロールオーバーアクションのためにmax_age閾値を使用しないようにします。代わりに、max_primary_shard_sizeを使用して、空のインデックスや多くの小さなシャードを作成しないようにします。

保持ポリシーがmax_age閾値を必要とする場合は、それを増やしてより長い時間間隔をカバーするインデックスを作成します。たとえば、毎日インデックスを作成する代わりに、週次または月次でインデックスを作成できます。

空のインデックスや不要なインデックスを削除する

ILMを使用していて、max_age閾値に基づいてインデックスをロールオーバーしている場合、ドキュメントのないインデックスを意図せず作成することがあります。これらの空のインデックスは何の利益も提供せず、リソースを消費し続けます。

これらの空のインデックスは、cat count APIを使用して見つけることができます。

Python

  1. resp = client.cat.count(
  2. index="my-index-000001",
  3. v=True,
  4. )
  5. print(resp)

Ruby

  1. response = client.cat.count(
  2. index: 'my-index-000001',
  3. v: true
  4. )
  5. puts response

Js

  1. const response = await client.cat.count({
  2. index: "my-index-000001",
  3. v: "true",
  4. });
  5. console.log(response);

Console

  1. GET _cat/count/my-index-000001?v=true

空のインデックスのリストができたら、delete index APIを使用して削除できます。他の不要なインデックスも削除できます。

Python

  1. resp = client.indices.delete(
  2. index="my-index-000001",
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.delete(
  2. index: 'my-index-000001'
  3. )
  4. puts response

Js

  1. const response = await client.indices.delete({
  2. index: "my-index-000001",
  3. });
  4. console.log(response);

Console

  1. DELETE my-index-000001

オフピーク時間に強制マージする

インデックスへの書き込みをもう行わない場合、force merge APIを使用して、より小さなセグメントをより大きなセグメントにマージできます。これにより、シャードのオーバーヘッドが減少し、検索速度が向上します。ただし、強制マージはリソースを大量に消費します。可能であれば、オフピーク時間に強制マージを実行してください。

Python

  1. resp = client.indices.forcemerge(
  2. index="my-index-000001",
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.forcemerge(
  2. index: 'my-index-000001'
  3. )
  4. puts response

Js

  1. const response = await client.indices.forcemerge({
  2. index: "my-index-000001",
  3. });
  4. console.log(response);

Console

  1. POST my-index-000001/_forcemerge

既存のインデックスをより少ないシャードに縮小する

インデックスへの書き込みをもう行わない場合、shrink index APIを使用してシャード数を減らすことができます。

ILMには、ウォームフェーズのインデックスに対して縮小アクションもあります。

小さなインデックスを結合する

reindex APIを使用して、類似のマッピングを持つインデックスを1つの大きなインデックスに結合することもできます。時系列データの場合、短い期間のインデックスを新しいインデックスに再インデックス化して、より長い期間をカバーすることができます。たとえば、10月の毎日のインデックスを、my-index-2099.10.11のような共有インデックスパターンで月次my-index-2099.10インデックスに再インデックス化できます。再インデックス化後は、小さなインデックスを削除します。

Python

  1. resp = client.reindex(
  2. source={
  3. "index": "my-index-2099.10.*"
  4. },
  5. dest={
  6. "index": "my-index-2099.10"
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.reindex(
  2. body: {
  3. source: {
  4. index: 'my-index-2099.10.*'
  5. },
  6. dest: {
  7. index: 'my-index-2099.10'
  8. }
  9. }
  10. )
  11. puts response

Js

  1. const response = await client.reindex({
  2. source: {
  3. index: "my-index-2099.10.*",
  4. },
  5. dest: {
  6. index: "my-index-2099.10",
  7. },
  8. });
  9. console.log(response);

Console

  1. POST _reindex
  2. {
  3. "source": {
  4. "index": "my-index-2099.10.*"
  5. },
  6. "dest": {
  7. "index": "my-index-2099.10"
  8. }
  9. }

シャード関連のエラーをトラブルシュートする

一般的なシャード関連のエラーを解決する方法は次のとおりです。

このアクションは[x]の合計シャードを追加しますが、このクラスターには現在[y]/[z]の最大シャードが開いています。

cluster.max_shards_per_nodeクラスター設定は、クラスターの最大オープンシャード数を制限します。このエラーは、アクションがこの制限を超えることを示しています。

変更がクラスターを不安定にしないと確信している場合は、クラスター設定の更新APIを使用して一時的に制限を増やし、アクションを再試行できます。

Python

  1. resp = client.cluster.put_settings(
  2. persistent={
  3. "cluster.max_shards_per_node": 1200
  4. },
  5. )
  6. print(resp)

Ruby

  1. response = client.cluster.put_settings(
  2. body: {
  3. persistent: {
  4. 'cluster.max_shards_per_node' => 1200
  5. }
  6. }
  7. )
  8. puts response

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. "cluster.max_shards_per_node": 1200,
  4. },
  5. });
  6. console.log(response);

Console

  1. PUT _cluster/settings
  2. {
  3. "persistent" : {
  4. "cluster.max_shards_per_node": 1200
  5. }
  6. }

この増加は一時的なものであるべきです。長期的な解決策として、オーバーシャーディングされたデータティアにノードを追加するか、クラスターのシャード数を減らすことをお勧めします。変更後のクラスターの現在のシャード数を取得するには、クラスター統計APIを使用します。

Python

  1. resp = client.cluster.stats(
  2. filter_path="indices.shards.total",
  3. )
  4. print(resp)

Ruby

  1. response = client.cluster.stats(
  2. filter_path: 'indices.shards.total'
  3. )
  4. puts response

Js

  1. const response = await client.cluster.stats({
  2. filter_path: "indices.shards.total",
  3. });
  4. console.log(response);

Console

  1. GET _cluster/stats?filter_path=indices.shards.total

長期的な解決策が整ったら、cluster.max_shards_per_node制限をリセットすることをお勧めします。

Python

  1. resp = client.cluster.put_settings(
  2. persistent={
  3. "cluster.max_shards_per_node": None
  4. },
  5. )
  6. print(resp)

Ruby

  1. response = client.cluster.put_settings(
  2. body: {
  3. persistent: {
  4. 'cluster.max_shards_per_node' => nil
  5. }
  6. }
  7. )
  8. puts response

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. "cluster.max_shards_per_node": null,
  4. },
  5. });
  6. console.log(response);

Console

  1. PUT _cluster/settings
  2. {
  3. "persistent" : {
  4. "cluster.max_shards_per_node": null
  5. }
  6. }

シャード内のドキュメント数は[2147483519]を超えることはできません

各Elasticsearchシャードは別々のLuceneインデックスであるため、LuceneのMAX_DOC制限である最大2,147,483,519((2^31)-129)ドキュメントを持つことができます。このシャードごとの制限は、Index stats APIによって報告されたdocs.countdocs.deletedの合計に適用されます。この制限を超えると、次のようなエラーが発生します:

Txt

  1. Elasticsearch exception [type=illegal_argument_exception, reason=Number of documents in the shard cannot exceed [2147483519]]

この計算は、Count APIの計算と異なる場合があります。なぜなら、Count APIはネストされたドキュメントを含まず、削除されたドキュメントをカウントしないからです。

この制限は、シャードごとの推奨最大ドキュメント数(約200Mドキュメント)よりもはるかに高いです。

この問題が発生した場合は、Force Merge APIを使用して削除されたドキュメントをマージすることで軽減を試みてください。たとえば:

Python

  1. resp = client.indices.forcemerge(
  2. index="my-index-000001",
  3. only_expunge_deletes=True,
  4. )
  5. print(resp)

Js

  1. const response = await client.indices.forcemerge({
  2. index: "my-index-000001",
  3. only_expunge_deletes: "true",
  4. });
  5. console.log(response);

Console

  1. POST my-index-000001/_forcemerge?only_expunge_deletes=true

これにより、Task Management APIを介して監視できる非同期タスクが開始されます。

不要なドキュメントを削除するか、インデックスを分割または再インデックス化して、より多くのシャードを持つインデックスにすることも役立つ場合があります。