Elasticsearch 2.1: Jendela hasil terlalu besar (index.max_result_window)

88

Kami mengambil informasi dari Elasticsearch 2.1 dan mengizinkan pengguna untuk membuka halaman melalui hasil. Ketika pengguna meminta nomor halaman yang tinggi, kami mendapatkan pesan kesalahan berikut:

Jendela hasil terlalu besar, dari + size harus kurang dari atau sama dengan: [10000] tetapi sebelumnya [10020]. Lihat api gulir untuk cara yang lebih efisien dalam meminta kumpulan data yang besar. Batas ini dapat disetel dengan mengubah parameter level indeks [index.max_result_window]

Docu elastis mengatakan bahwa ini karena konsumsi memori yang tinggi dan menggunakan api gulir:

Nilai yang lebih tinggi dari dapat menghabiskan banyak memori heap per pencarian dan per pecahan yang menjalankan pencarian. Paling aman meninggalkan nilai ini karena ini adalah penggunaan api gulir untuk pengguliran dalam apa pun https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Masalahnya adalah saya tidak ingin mengambil kumpulan data yang besar. Saya hanya ingin mengambil sepotong dari kumpulan data yang sangat tinggi di kumpulan hasil. Juga docu bergulir mengatakan:

Pengguliran tidak dimaksudkan untuk permintaan pengguna waktu nyata https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Ini membuat saya memiliki beberapa pertanyaan:

1) Akankah konsumsi memori benar-benar lebih rendah (ada jika demikian mengapa) jika saya menggunakan api gulir untuk menggulir ke atas hingga hasil 10020 (dan mengabaikan semua yang di bawah 10000) daripada melakukan permintaan pencarian "normal" untuk hasil 10000-10020?

2) Tampaknya API gulir merupakan pilihan bagi saya tetapi saya harus meningkatkan "index.max_result_window". Apakah ada yang punya pengalaman dengan ini?

3) Apakah ada opsi lain untuk menyelesaikan masalah saya?

Ronald
sumber

Jawaban:

80

Jika Anda membutuhkan penomoran halaman yang dalam, salah satu solusi yang mungkin adalah meningkatkan nilainya max_result_window. Anda dapat menggunakan curluntuk melakukan ini dari baris perintah shell Anda:

curl -XPUT "http://localhost:9200/my_index/_settings" -H 'Content-Type: application/json' -d '{ "index" : { "max_result_window" : 500000 } }'

Saya tidak melihat peningkatan penggunaan memori, untuk nilai ~ 100k.

Andrey Morozov
sumber
Saya memiliki kesalahan yang sama 'Result window is too large, from + size must be less than or equal to: [10000] but was [47190]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level parameter.')Dikatakan memiliki 4719 halaman (setiap halaman 10 hasil). dan saya pikir saran Anda berhasil.
dotslash
1
Ini adalah solusi yang bagus untuk sejumlah kecil dokumen kurang dari 500000
Ezzat
2
Saya menggunakan ES v2.2.0 dan saya harus mengubah payload menjadi { "max_result_window" : 500000 }agar ini berfungsi. Jadi perintah curl menjadi -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha
3
bagi mereka yang mendapatkan kesalahan header dengan perintah ini untuk versi elasticsearch yang lebih baru, Anda juga harus meneruskan header, curl -XPUT " localhost: 9200 / my_index / _settings " -H "Content-Type: application / json" -d '{ "index": {"max_result_window": 50000}} '
Satys
32

Solusi yang tepat adalah menggunakan scrolling.
Namun, jika Anda ingin memperluas searchpengembalian hasil melebihi 10.000 hasil, Anda dapat melakukannya dengan mudah dengan Kibana:

Pergi ke Dev Toolsdan posting yang berikut ini ke indeks Anda (nama_anda_anda), tentukan apa yang akan menjadi jendela hasil maksimal yang baru

masukkan deskripsi gambar di sini

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Jika semuanya berjalan dengan baik, Anda akan melihat respons sukses berikut:

{
  "acknowledged": true
}
Guy Dubrovski
sumber
1
Saya mencoba mengikuti cara melakukan ini di kode elasticsearch (put_settings dll ..) dan mencapai banyak kesalahan. Ini menghemat waktu berjam-jam! Terima kasih!
cpres
25

Halaman-halaman berikut dalam dokumentasi elastis berbicara tentang deep paging:

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

Bergantung pada ukuran dokumen Anda, jumlah shard, dan perangkat keras yang Anda gunakan, paging 10.000 hingga 50.000 hasil (1.000 hingga 5.000 halaman) sedalam harus dapat dilakukan dengan sempurna. Tetapi dengan nilai from yang cukup besar, proses pengurutan bisa menjadi sangat berat, menggunakan CPU, memori, dan bandwidth dalam jumlah besar. Untuk alasan ini, kami sangat menyarankan agar paging dalam tidak digunakan.

Ronald
sumber
1
Jadi di sini, kita harus meninggalkan pagination yang dalam, bukan? Pada dasarnya tidak ada arti paging 4000 halaman untuk satu penampil. Katakanlah, pencarian google, hampir tidak kita menggulir ke halaman 8 atau 9 untuk memeriksa hasil. Biasanya kami hanya mengurus 3-5 halaman teratas yang diberikan Google kepada kami.
dotslash
2
Bisakah kita menggunakan API gulir jika kita membutuhkan penomoran halaman yang dalam?
Abhi.G
3
Tetapi ketika kami mengaktifkan fitur sortir, katakanlah di situs eCommerce. ketika pengguna ingin melihat barang dengan harga tertinggi. Hasilnya akan berbeda ketika kita mengurutkan berdasarkan harga tertinggi dibandingkan ketika kita mengurutkan berdasarkan halaman terendah tetapi pergi ke halaman terakhir bukan? karena kami membatasi jumlah hasil yang dapat diakses. ada solusi untuk ini?
MR Murazza
3

Gunakan Scroll API untuk mendapatkan lebih dari 10.000 hasil.

Contoh gulir di ElasticSearch NEST API

Saya telah menggunakannya seperti ini:

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();
}
Morten Holmgaard
sumber
0

Jika Anda menginginkan lebih dari 10.000 hasil maka di semua node data penggunaan memori akan sangat tinggi karena harus mengembalikan lebih banyak hasil di setiap permintaan kueri. Kemudian jika Anda memiliki lebih banyak data dan lebih banyak pecahan, penggabungan hasil tersebut tidak akan efisien. Juga es cache konteks filter, karenanya lebih banyak memori. Anda harus coba-coba berapa banyak tepatnya yang Anda ambil. Jika Anda mendapatkan banyak permintaan di jendela kecil, Anda harus melakukan beberapa kueri selama lebih dari 10k dan menggabungkannya sendiri ke dalam kode, yang seharusnya mengambil lebih sedikit memori aplikasi daripada jika Anda meningkatkan ukuran jendela.

amritoit
sumber
0

2) Tampaknya API gulir merupakan pilihan bagi saya tetapi saya harus meningkatkan "index.max_result_window". Apakah ada yang punya pengalaman dengan ini?

-> Anda dapat menentukan nilai ini di templat indeks, templat es hanya akan berlaku untuk indeks baru, jadi Anda harus menghapus indeks lama setelah membuat templat atau menunggu data baru diserap di elasticsearch.

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

Sindhu
sumber
0

Dalam kasus saya, sepertinya mengurangi hasil melalui awalan from & size ke kueri akan menghapus kesalahan karena kami tidak memerlukan semua hasil:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
FlimFlam Vir
sumber