web-dev-qa-db-ja.com

Elasticsearch 2.1:結果ウィンドウが大きすぎます(index.max_result_window)

Elasticsearch 2.1から情報を取得し、ユーザーが結果をページングできるようにします。ユーザーが高いページ番号を要求すると、次のエラーメッセージが表示されます。

結果ウィンドウが大きすぎます。開始サイズは[10000]以下である必要がありますが、[10020]でした。大きなデータセットを要求するより効率的な方法については、スクロールAPIを参照してください。この制限は、[index.max_result_window]インデックスレベルパラメーターを変更することで設定できます

エラスティックドキュメントは、これはメモリ消費量が多いため、スクロールAPIを使用するためであると述べています。

より大きい値は、検索ごとおよび検索を実行するシャードごとにヒープメモリのかなりの部分を消費する可能性があります。ディープスクロールにはスクロールAPIを使用するため、この値を残すのが最も安全です https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

問題は、大きなデータセットを取得したくないということです。結果セットの非常に高いデータセットからスライスを取得したいだけです。また、スクロール文書には次のように書かれています。

スクロールはリアルタイムのユーザーリクエスト用ではありません https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

これにはいくつかの質問があります:

1)スクロールAPIを使用して、結果10000-10020に対して「通常の」検索要求を行うのではなく、結果10020までスクロールする(そして10000未満のすべてを無視する)場合、メモリ消費は実際に低くなりますか?

2)スクロールAPIは私にとってオプションではないようですが、 "index.max_result_window"を増やす必要があります。誰もこれを経験したことがありますか?

3)問題を解決する他のオプションはありますか?

75
Ronald

エラスティックドキュメントの次のページでは、ディープページングについて説明しています。

https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.htmlhttps://www.elastic.co/guide/en/elasticsearch/ guide/current/_fetch_phase.html

ドキュメントのサイズ、シャードの数、および使用しているハードウェアに応じて、10,000〜50,000の結果(1,000〜5,000ページ)の深さのページングが完全に実行可能になります。しかし、値から大きくなると、膨大な量のCPU、メモリ、帯域幅を使用して、ソートプロセスが実際に非常に重くなる可能性があります。このため、ディープページングを強くお勧めします。

20
Ronald

大きな深いページネーションが必要な場合、ソリューションの1つのバリエーションは値max_result_windowを増やすことだけだと思います

curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "index" : { "max_result_window" : 500000 } }'

メモリ使用量の増加、私は〜100kの値が見つかりません

72
Andrey Morozov

適切な解決策は、スクロールを使用することです。
ただし、searchが返す結果を10,000を超える結果に拡張する場合は、Kibanaを使用して簡単に実行できます。

Dev Toolsに移動し、インデックス(your_index_name)に次を投稿し、新しい最大結果ウィンドウを指定します

enter image description here

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

すべてうまくいけば、次の成功応答が表示されるはずです。

{
  "acknowledged": true
}
25
Guy Dubrovski

Scroll APIを使用して、10000を超える結果を取得します。

ElasticSearch NEST APIのスクロール例

私はこれを次のように使用しました:

private static Customer[] GetCustomers(IElasticClient elasticClient)
{
    var customers = new List<Customer>();
    var searchResult = elasticClient.Search<Customer>(s => s.Index(IndexAlias.ForCustomers())
                          .Size(10000).SearchType(SearchType.Scan).Scroll("1m"));

    do
    {
        var result = searchResult;
        searchResult = elasticClient.Scroll<Customer>("1m", result.ScrollId);
        customers.AddRange(searchResult.Documents);
    } while (searchResult.IsValid && searchResult.Documents.Any());

    return customers.ToArray();
}
2

2)スクロールAPIは私にとってオプションではないようですが、 "index.max_result_window"を増やす必要があります。誰もこれを経験したことがありますか?

->インデックステンプレートでこの値を定義できます。esテンプレートは新しいインデックスのみに適用されるため、テンプレートの作成後に古いインデックスを削除するか、elasticsearchで新しいデータが取り込まれるのを待つ必要があります。

{"order":1、 "template": "index_template *"、 "settings":{"index.number_of_replicas": "0"、 "index.number_of_shards": "1"、 "index.max_result_window":2147483647}、

0
Sindhu

10000を超える結果が必要な場合、すべてのデータノードで、各クエリ要求でより多くの結果を返す必要があるため、メモリ使用量が非常に高くなります。その後、より多くのデータとより多くのシャードがある場合、それらの結果をマージすることは非効率的です。また、esはフィルターコンテキストをキャッシュするため、メモリが増えます。どれだけ正確に服用しているかを試行錯誤する必要があります。小さなウィンドウで多くのリクエストを取得している場合は、10k以上の複数のクエリを実行し、コードでそれを自分でマージする必要があります。

0
Amritendu