Split index API

既存のインデックスを新しいインデックスに分割し、より多くのプライマリシャードを持たせます。

Python

  1. resp = client.indices.split(
  2. index="my-index-000001",
  3. target="split-my-index-000001",
  4. settings={
  5. "index.number_of_shards": 2
  6. },
  7. )
  8. print(resp)

Ruby

  1. response = client.indices.split(
  2. index: 'my-index-000001',
  3. target: 'split-my-index-000001',
  4. body: {
  5. settings: {
  6. 'index.number_of_shards' => 2
  7. }
  8. }
  9. )
  10. puts response

Js

  1. const response = await client.indices.split({
  2. index: "my-index-000001",
  3. target: "split-my-index-000001",
  4. settings: {
  5. "index.number_of_shards": 2,
  6. },
  7. });
  8. console.log(response);

Console

  1. POST /my-index-000001/_split/split-my-index-000001
  2. {
  3. "settings": {
  4. "index.number_of_shards": 2
  5. }
  6. }

Request

POST /<index>/_split/<target-index>

PUT /<index>/_split/<target-index>

Prerequisites

  • Elasticsearchのセキュリティ機能が有効になっている場合、インデックスに対してmanage インデックス権限を持っている必要があります。
  • インデックスを分割する前に:
    • インデックスは読み取り専用でなければなりません。
    • クラスタの健康状態が緑でなければなりません。

次のリクエストを使用して、インデックスを読み取り専用にすることができます。インデックスブロックの追加 APIを使用します:

Python

  1. resp = client.indices.add_block(
  2. index="my_source_index",
  3. block="write",
  4. )
  5. print(resp)

Ruby

  1. response = client.indices.add_block(
  2. index: 'my_source_index',
  3. block: 'write'
  4. )
  5. puts response

Js

  1. const response = await client.indices.addBlock({
  2. index: "my_source_index",
  3. block: "write",
  4. });
  5. console.log(response);

Console

  1. PUT /my_source_index/_block/write

データストリームの現在の書き込みインデックスは分割できません。現在の書き込みインデックスを分割するには、最初にデータストリームをロールオーバーして新しい書き込みインデックスを作成し、その後に以前の書き込みインデックスを分割する必要があります。

Description

スプリットインデックスAPIを使用すると、既存のインデックスを新しいインデックスに分割できます。この新しいインデックスでは、元の各プライマリシャードが2つ以上のプライマリシャードに分割されます。

インデックスを分割できる回数(および各元のシャードが分割できるシャードの数)は、index.number_of_routing_shards設定によって決まります。ルーティングシャードの数は、内部でドキュメントを一貫したハッシュでシャードに分配するために使用されるハッシュ空間を指定します。たとえば、number_of_routing_shards305 x 2 x 3)に設定された5シャードインデックスは、2または3の因子で分割できます。言い換えれば、次のように分割できます:

  • 51030(2で分割し、次に3で分割)
  • 51530(3で分割し、次に2で分割)
  • 530(6で分割)
  1. **インデックス作成の例**
  2. 次の[インデックス作成API](/read/elasticsearch-8-15/b5c127aabf881d48.md)は、`````my-index-000001`````インデックスを`````index.number_of_routing_shards`````設定の`````30`````で作成します。
  3. #### Python
  4. ``````python
  5. resp = client.indices.create(
  6. index="my-index-000001",
  7. settings={
  8. "index": {
  9. "number_of_routing_shards": 30
  10. }
  11. },
  12. )
  13. print(resp)
  14. `

Ruby

  1. response = client.indices.create(
  2. index: 'my-index-000001',
  3. body: {
  4. settings: {
  5. index: {
  6. number_of_routing_shards: 30
  7. }
  8. }
  9. }
  10. )
  11. puts response

Js

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

Console

  1. PUT /my-index-000001
  2. {
  3. "settings": {
  4. "index": {
  5. "number_of_routing_shards": 30
  6. }
  7. }
  8. }
  1. 元のインデックスに1つのプライマリシャードが含まれている場合(またはマルチシャードインデックスが[縮小](/read/elasticsearch-8-15/b71a275dcf175740.md)されて単一のプライマリシャードになった場合)、インデックスは1より大きい任意の数のシャードに分割できます。デフォルトのルーティングシャードの数の特性は、新しく分割されたインデックスに適用されます。
  2. ### How splitting works
  3. 分割操作:
  4. - 1*.* ソースインデックスと同じ定義を持つ新しいターゲットインデックスを作成しますが、プライマリシャードの数が多くなります。
  5. - 2*.* ソースインデックスからターゲットインデックスにセグメントをハードリンクします。(ファイルシステムがハードリンクをサポートしていない場合、すべてのセグメントが新しいインデックスにコピーされますが、これははるかに時間がかかるプロセスです。)
  6. - 3*.* 低レベルのファイルが作成された後、すべてのドキュメントを再ハッシュして、異なるシャードに属するドキュメントを削除します。
  7. - 4*.* ターゲットインデックスを、ちょうど再オープンされたクローズドインデックスのように回復します。
  8. ### Why doesn’t Elasticsearch support incremental resharding?
  9. `````N`````シャードから`````N+1`````シャードへの移行、すなわちインクリメンタルリシャーディングは、確かに多くのキー・バリュー・ストアでサポートされている機能です。新しいシャードを追加し、その新しいシャードに新しいデータをプッシュするだけではオプションではありません。これはインデックスのボトルネックになる可能性が高く、ドキュメントが`````_id`````に基づいてどのシャードに属するかを特定することが、取得、削除、更新リクエストに必要であり、非常に複雑になります。これは、異なるハッシュスキームを使用して既存のデータを再バランスする必要があることを意味します。
  10. キー・バリュー・ストアがこれを効率的に行う最も一般的な方法は、一貫したハッシュを使用することです。一貫したハッシュは、`````N`````から`````N+1`````にシャードの数を増やすときに、`````1/N`````-分のキーを再配置するだけで済みます。しかし、Elasticsearchのストレージ単位であるシャードはLuceneインデックスです。その検索指向のデータ構造のため、Luceneインデックスのかなりの部分を取り出し、たとえそれがドキュメントの5%だけであっても、それを削除して別のシャードにインデックスすることは、キー・バリュー・ストアよりもはるかに高いコストがかかります。このコストは、上記のセクションで説明したように、乗数因子でシャードの数を増やすときに合理的に保たれます。これにより、Elasticsearchはローカルで分割を実行でき、移動する必要のあるドキュメントを再インデックスするのではなく、インデックスレベルで分割を実行できるようになります。また、効率的なファイルコピーのためにハードリンクを使用することもできます。
  11. 追加専用データの場合、新しいインデックスを作成し、新しいデータをそこにプッシュすることで、より柔軟性を得ることが可能です。その際、古いインデックスと新しいインデックスの両方をカバーするエイリアスを追加します。古いインデックスと新しいインデックスがそれぞれ`````M``````````N`````シャードを持っていると仮定すると、`````M+N`````シャードを持つインデックスを検索するのと比較して、オーバーヘッドはありません。
  12. ### Split an index
  13. `````my_source_index``````````my_target_index`````という新しいインデックスに分割するには、次のリクエストを発行します:
  14. #### Python
  15. ``````python
  16. resp = client.indices.split(
  17. index="my_source_index",
  18. target="my_target_index",
  19. settings={
  20. "index.number_of_shards": 2
  21. },
  22. )
  23. print(resp)
  24. `

Ruby

  1. response = client.indices.split(
  2. index: 'my_source_index',
  3. target: 'my_target_index',
  4. body: {
  5. settings: {
  6. 'index.number_of_shards' => 2
  7. }
  8. }
  9. )
  10. puts response

Js

  1. const response = await client.indices.split({
  2. index: "my_source_index",
  3. target: "my_target_index",
  4. settings: {
  5. "index.number_of_shards": 2,
  6. },
  7. });
  8. console.log(response);

Console

  1. POST /my_source_index/_split/my_target_index
  2. {
  3. "settings": {
  4. "index.number_of_shards": 2
  5. }
  6. }

上記のリクエストは、ターゲットインデックスがクラスタ状態に追加されるとすぐに返されます。分割操作が開始されるのを待ちません。

インデックスは、次の要件を満たす場合にのみ分割できます:

  • ターゲットインデックスは存在してはいけません
  • ソースインデックスはターゲットインデックスよりも少ないプライマリシャードを持っている必要があります。
  • ターゲットインデックスのプライマリシャードの数は、ソースインデックスのプライマリシャードの数の倍数でなければなりません。
  • 分割プロセスを処理するノードは、既存のインデックスの2番目のコピーを収容するのに十分な空きディスクスペースを持っている必要があります。

_split APIは、create index APIに似ており、ターゲットインデックスのsettingsおよびaliasesパラメータを受け入れます:

Python

  1. resp = client.indices.split(
  2. index="my_source_index",
  3. target="my_target_index",
  4. settings={
  5. "index.number_of_shards": 5
  6. },
  7. aliases={
  8. "my_search_indices": {}
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.indices.split(
  2. index: 'my_source_index',
  3. target: 'my_target_index',
  4. body: {
  5. settings: {
  6. 'index.number_of_shards' => 5
  7. },
  8. aliases: {
  9. my_search_indices: {}
  10. }
  11. }
  12. )
  13. puts response

Js

  1. const response = await client.indices.split({
  2. index: "my_source_index",
  3. target: "my_target_index",
  4. settings: {
  5. "index.number_of_shards": 5,
  6. },
  7. aliases: {
  8. my_search_indices: {},
  9. },
  10. });
  11. console.log(response);

Console

  1. POST /my_source_index/_split/my_target_index
  2. {
  3. "settings": {
  4. "index.number_of_shards": 5
  5. },
  6. "aliases": {
  7. "my_search_indices": {}
  8. }
  9. }
ターゲットインデックスのシャードの数。これはソースインデックスのシャードの数の倍数でなければなりません。

マッピングは_splitリクエストで指定できません。

Monitor the split process

分割プロセスは、_cat recovery APIで監視できます。また、cluster health APIを使用して、wait_for_statusパラメータをyellowに設定することで、すべてのプライマリシャードが割り当てられるまで待つこともできます。

_split APIは、ターゲットインデックスがクラスタ状態に追加されるとすぐに返され、シャードが割り当てられる前に返されます。この時点で、すべてのシャードはunassignedの状態にあります。何らかの理由でターゲットインデックスが割り当てられない場合、そのプライマリシャードはunassignedのままで、そのノードに割り当てられるまで待機します。

プライマリシャードが割り当てられると、initializingの状態に移行し、分割プロセスが開始されます。分割操作が完了すると、シャードはactiveになります。この時点で、Elasticsearchはレプリカを割り当てようとし、プライマリシャードを別のノードに移動することを決定する場合があります。

Wait for active shards

分割操作は新しいインデックスを作成してシャードを分割するため、インデックス作成時のアクティブシャードを待つ設定は分割インデックスアクションにも適用されます。

Path parameters

  • <index>
  • (必須、文字列)分割するソースインデックスの名前。
  • <target-index>
  • (必須、文字列)作成するターゲットインデックスの名前。
    インデックス名は次の基準を満たす必要があります:
    • 小文字のみ
    • \/*?"<>| (スペース文字)、,#を含むことはできません
    • 7.0以前のインデックスはコロン(:)を含むことができましたが、これは非推奨となり、7.0以降はサポートされません
    • -_+で始めることはできません
    • .または..であってはなりません
    • 255バイトを超えてはなりません(バイト数なので、マルチバイト文字は255の制限に早くカウントされます)
    • .で始まる名前は非推奨であり、隠しインデックスおよびプラグインによって管理される内部インデックスを除きます。

Query parameters

  • wait_for_active_shards
  • (オプション、文字列)操作を進める前にアクティブでなければならないシャードのコピーの数。allまたはインデックス内のシャードの総数(number_of_replicas+1)までの任意の正の整数に設定します。デフォルト: 1、プライマリシャード。
    アクティブシャードを参照してください。
  • master_timeout
  • (オプション、時間単位)マスターノードを待つ期間。タイムアウトが切れる前にマスターノードが利用できない場合、リクエストは失敗し、エラーが返されます。デフォルトは30sです。リクエストがタイムアウトしないことを示すために-1に設定することもできます。
  • timeout
  • (オプション、時間単位)クラスタメタデータを更新した後、クラスタ内のすべての関連ノードからの応答を待つ期間。タイムアウトが切れる前に応答が受信されない場合、クラスタメタデータの更新は適用されますが、応答は完全に承認されなかったことを示します。デフォルトは30sです。リクエストがタイムアウトしないことを示すために-1に設定することもできます。

Request body

  • aliases
  • (オプション、オブジェクトのオブジェクト)結果インデックスのエイリアス。
    1. - `````<alias>
    • (必須、オブジェクト)キーはエイリアス名です。インデックスエイリアス名は日付数学をサポートしています。
      オブジェクトボディにはエイリアスのオプションが含まれます。空のオブジェクトをサポートします。
      1. - `````filter
      • (オプション、クエリDSLオブジェクト)エイリアスがアクセスできるドキュメントを制限するために使用されるクエリ。
      • index_routing
      • (オプション、文字列)特定のシャードにインデックス操作をルーティングするために使用される値。指定された場合、これはインデックス操作のrouting値を上書きします。
      • is_hidden
      • (オプション、ブール値)trueの場合、エイリアスは隠しです。デフォルトはfalseです。エイリアスのすべてのインデックスは同じis_hidden値を持っている必要があります。
      • is_write_index
      • (オプション、ブール値)trueの場合、インデックスはエイリアスの書き込みインデックスです。デフォルトはfalseです。
      • routing
      • (オプション、文字列)特定のシャードにインデックスおよび検索操作をルーティングするために使用される値。
      • search_routing
      • (オプション、文字列)特定のシャードに検索操作をルーティングするために使用される値。指定された場合、これは検索操作のrouting値を上書きします。
  • settings
  • (オプション、インデックス設定オブジェクト)ターゲットインデックスの構成オプション。 インデックス設定を参照してください。