Elasticsearch 2.1: Sonuç penceresi çok büyük (index.max_result_window)


88

Elasticsearch 2.1'den bilgi alıyoruz ve kullanıcının sonuçlara göz atmasına izin veriyoruz. Kullanıcı yüksek bir sayfa numarası istediğinde aşağıdaki hata mesajını alırız:

Sonuç penceresi çok büyük, + boyutundan küçük veya şuna eşit olmalıdır: [10000] ama [10020] idi. Büyük veri kümelerini talep etmenin daha verimli bir yolu için kaydırma api'sine bakın. Bu sınır, [index.max_result_window] dizin seviyesi parametresi değiştirilerek ayarlanabilir

Esnek belge, bunun yüksek bellek tüketiminden ve kayan api kullanımından kaynaklandığını söylüyor:

Daha yüksek değerler, aramayı yürüten her arama ve parça başına önemli yığın bellek parçalarını tüketebilir. Herhangi bir derin kaydırma için kaydırma api'sini kullanmak olduğu için bu değeri bırakmak en güvenli yoldur https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Mesele şu ki, büyük veri kümelerini almak istemiyorum. Veri kümesinden yalnızca sonuç kümesinde çok yüksek olan bir dilim almak istiyorum. Ayrıca kayan belge şöyle diyor:

Kaydırma, gerçek zamanlı kullanıcı istekleri için tasarlanmamıştır https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Bu bana bazı sorular bırakıyor:

1) 10000-10020 sonucu için "normal" bir arama isteği yerine 10020 sonucuna gitmek için kaydırma apisini kullanırsam (ve 10000'in altındaki her şeyi göz ardı edersem) bellek tüketimi gerçekten daha düşük olur mu (eğer öyleyse neden)?

2) Kaydırma API'sı benim için bir seçenek gibi görünmüyor, ancak "index.max_result_window" u artırmam gerekiyor. Bununla ilgili deneyimi olan var mı?

3) Sorunumu çözmek için başka seçenekler var mı?

Yanıtlar:


80

Derin sayfalandırmaya ihtiyacınız varsa, olası çözümlerden biri değeri artırmaktır max_result_window. Bunu curlkabuk komut satırınızdan yapmak için kullanabilirsiniz :

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

~ 100k değerlerinde bellek kullanımının arttığını fark etmedim.


Aynı hatayı aldım '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.')4719 sayfası olduğunu söyledi (her sayfa 10 sonuç). ve bence öneriniz işe yarıyor.
nokta işareti

1
Bu, 500.000'den az olan az miktardaki belge için iyi bir çözüm
Ezzat

2
ES v2.2.0 kullanıyorum ve bunun { "max_result_window" : 500000 }çalışması için yükü olarak değiştirmem gerekti . Böylece curl komutu oldu -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha

3
elasticsearch'ün daha yeni sürümü için bu komutla başlık hatası alanlar için, curl -XPUT " localhost: 9200 / my_index / _settings " -H "Content-Type: application / json" -d '{ "index": {"max_result_window": 50000}} '
Satys

32

Doğru çözüm kaydırmayı kullanmak olacaktır.
Ancak, sonuç searchgetirilerini 10.000 sonucun ötesine genişletmek istiyorsanız, bunu Kibana ile kolayca yapabilirsiniz:

Dev ToolsYeni maksimum sonuç penceresinin ne olacağını belirterek aşağıdakileri dizininize (dizin_adınız) gidin ve gönderin

görüntü açıklamasını buraya girin

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Her şey yolunda giderse, aşağıdaki başarılı yanıtı görmelisiniz:

{
  "acknowledged": true
}

1
Elasticsearch kodunda (put_settings vs ..) bunu yapmanın yolunu denedim ve birçok hataya ulaştım. Bu bana saatler kazandırıyor! Teşekkür ederim!
2017

25

Esnek dokümantasyondaki aşağıdaki sayfalar derin sayfalandırmadan bahsediyor:

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

Belgelerinizin boyutuna, parça sayısına ve kullandığınız donanıma bağlı olarak, 10.000 ila 50.000 sonuç (1.000 ila 5.000 sayfa) derinliğinde sayfalama mükemmel şekilde yapılabilir. Ancak değerlerden yeterince büyük olduğunda, büyük miktarda CPU, bellek ve bant genişliği kullanarak sıralama süreci gerçekten çok ağır hale gelebilir. Bu nedenle, derin sayfalamaya karşı şiddetle tavsiye ediyoruz.


1
Yani burada, derin sayfalandırmayı bırakmalıyız, değil mi? Temel olarak, tek bir görüntüleyici için 4000 sayfayı çağırmanın bir anlamı yoktur. Diyelim ki, google arama, sonuçları kontrol etmek için 8. veya 9. sayfaya neredeyse hiç geçmiyoruz. Genellikle yalnızca Google'ın bize verdiği ilk 3-5 sayfayla ilgileniriz.
nokta işareti

2
Derin sayfalandırmaya ihtiyacımız olması durumunda kaydırma API'sini kullanabilir miyiz?
Abhi.G

3
Ancak sıralama özelliğini etkinleştirdiğimizde, bir e-ticaret sitesinde diyelim. Kullanıcı en yüksek fiyatlı ürünleri görmek istediğinde. En düşük sayfaya göre sıraladığımızda ancak son sayfaya gittiğimizde en yüksek fiyata göre sıraladığımızda sonuç farklı olacaktır, değil mi? ulaşılabilecek sonuç sayısını sınırladığımız için. bunun için herhangi bir çalışma var mı?
MR Murazza

3

10000'den fazla sonuç almak için Scroll API'yi kullanın.

ElasticSearch NEST API'de kaydırma örneği

Bunu şu şekilde kullandım:

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();
}

0

10000'den fazla sonuç istiyorsanız, tüm veri düğümlerinde bellek kullanımı çok yüksek olacaktır çünkü her sorgu isteğinde daha fazla sonuç döndürmesi gerekir. Daha fazla veriniz ve daha fazla parçanız varsa, bu sonuçları birleştirmek verimsiz olacaktır. Ayrıca filtre içeriğini önbelleğe alır, dolayısıyla yine daha fazla bellek. Tam olarak ne kadar aldığınızı denemeniz ve yanılmanız gerekir. Küçük bir pencerede çok sayıda istek alıyorsanız, 10.000'den fazla için birden fazla sorgu yapmalı ve bunu kodda kendi başına birleştirmelisiniz, bu da pencere boyutunu artırırsanız daha az uygulama belleği gerektirecektir.


0

2) Kaydırma API'sı benim için bir seçenek gibi görünmüyor, ancak "index.max_result_window" u artırmam gerekiyor. Bununla ilgili deneyimi olan var mı?

-> Bu değeri dizin şablonlarında tanımlayabilirsiniz, es şablon yalnızca yeni dizinler için geçerli olacaktır, bu nedenle ya şablonu oluşturduktan sonra eski dizinleri silmeniz ya da yeni verilerin elasticsearch'te beslenmesini beklemeniz gerekir.

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


0

Benim durumumda, sonuçların from & size önekleriyle sorguya indirilmesi hatayı ortadan kaldıracak gibi görünüyor çünkü tüm sonuçlara ihtiyacımız yok:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.