web-dev-qa-db-fra.com

Elasticsearch 2.1: La fenêtre de résultat est trop grande (index.max_result_window)

Nous récupérons les informations d’Elasticsearch 2.1 et permettons à l’utilisateur de parcourir les résultats. Lorsque l'utilisateur demande un numéro de page élevé, nous obtenons le message d'erreur suivant:

La fenêtre de résultat est trop grande, la taille de + doit être inférieure ou égale à: [10000] mais était de [10020]. Voir l’API de défilement pour un moyen plus efficace de demander de grands ensembles de données. Cette limite peut être définie en modifiant le paramètre de niveau d'index [index.max_result_window].

Le docu élastique dit que cela est dû à une consommation de mémoire importante et à l'utilisation de l'API de défilement:

Des valeurs supérieures à ce que peuvent consommer des morceaux significatifs de mémoire de tas par recherche et par fragment exécutant la recherche. Il est plus sûr de laisser cette valeur car il s'agit d'une API de défilement pour tout défilement en profondeur https://www.elastic.co/guide/fr/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Le fait est que je ne veux pas récupérer de grands ensembles de données. Je veux seulement récupérer une tranche de l'ensemble de données qui est très haut dans l'ensemble de résultats. Aussi le document défilant dit:

Le défilement n'est pas destiné aux demandes d'utilisateurs en temps réel https://www.elastic.co/guide/fr/elasticsearch/reference/2.2/search-request-scroll.html

Cela me laisse avec quelques questions:

1) La consommation de mémoire sera-t-elle réellement plus faible (quelle que soit la raison, si), si j'utilise l'api de défilement pour faire défiler jusqu'au résultat 10020 (et ignore tout ce qui se trouve en dessous de 10000) au lieu de faire une demande de recherche "normale" pour le résultat 10000-10020?

2) Il ne semble pas que l’API de défilement soit une option pour moi mais je dois augmenter "index.max_result_window". Est-ce que quelqu'un a de l'expérience avec ça?

3) Existe-t-il d'autres options pour résoudre mon problème?

77
Ronald

Les pages suivantes de la documentation élastique traitent de la pagination en profondeur:

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

Selon la taille de vos documents, le nombre de fragments et le matériel utilisé, paginer de 10 000 à 50 000 résultats (1 000 à 5 000 pages) devrait être parfaitement réalisable. Mais avec suffisamment de valeurs, le processus de tri peut devenir très lourd, en utilisant de grandes quantités de CPU, de mémoire et de bande passante. Pour cette raison, nous vous déconseillons fortement la pagination en profondeur.

21
Ronald

Si vous avez besoin d'une grande pagination en profondeur, je pense qu'une seule variante de solution consiste à augmenter la valeur max_result_window

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

L'augmentation de l'utilisation de la mémoire, I n'est pas trouvée pour des valeurs de ~ 100k

72
Andrey Morozov

La bonne solution serait d'utiliser le défilement.
Cependant, si vous souhaitez prolonger les résultats search retourne au-delà de 10 000 résultats, vous pouvez le faire facilement avec Kibana:

Allez à Dev Tools et postez simplement ce qui suit dans votre index (votre_nom_index), en spécifiant ce que serait la nouvelle fenêtre de résultat max.

enter image description here

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Si tout se passe bien, vous devriez voir la réponse suivante:

{
  "acknowledged": true
}
26
Guy Dubrovski

Utilisez l'API Scroll pour obtenir plus de 10 000 résultats.

Exemple de défilement dans l'API ElasticSearch NEST

Je l'ai utilisé comme ça:

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
Morten Holmgaard

2) Il ne semble pas que l’API de défilement soit une option pour moi, mais je dois augmenter "index.max_result_window". Est-ce que quelqu'un a de l'expérience avec ça?

-> Vous pouvez définir cette valeur dans les modèles d'index. Ce modèle ne s'appliquera qu'aux nouveaux index. Vous devez donc supprimer les anciens index après la création du modèle ou attendre que de nouvelles données soient capturées dans elasticsearch.

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

0
Sindhu

Si vous voulez plus de 10000 résultats, l'utilisation de la mémoire sera très élevée dans tous les nœuds de données car il doit renvoyer plus de résultats dans chaque requête. Ensuite, si vous avez plus de données et plus de fragments, la fusion de ces résultats sera inefficace. Aussi es cache le contexte de filtre, donc encore une fois plus de mémoire. Vous devez essayer et erreur combien vous prenez exactement. Si vous recevez de nombreuses requêtes dans une petite fenêtre, vous devez effectuer plusieurs requêtes pour plus de 10 000 $ et les fusionner par vous-même dans le code, ce qui est supposé prendre moins de mémoire d'application que si vous augmentez la taille de la fenêtre.

0
Amritendu