Guide des performances d'indexation Elasticsearch : bonnes pratiques dévoilées

Améliorez l'indexation Elasticsearch avec des requêtes groupées, le réglage du rafraîchissement et des répliques, les choix de mapping, les vérifications matérielles et la planification des shards.

Guide des performances d'indexation Elasticsearch : bonnes pratiques dévoilées

Les performances d'indexation Elasticsearch deviennent visibles lorsque votre pipeline d'ingestion commence à saturer, que les requêtes groupées sont rejetées ou que les recherches ralentissent lors d'écritures intensives. La solution n'est rarement un seul paramètre magique ; vous devez ajuster ensemble la taille des requêtes, le comportement de rafraîchissement, les mappings, la disposition des shards et le matériel.

Ce guide se concentre sur les vérifications pratiques des performances d'indexation Elasticsearch que vous pouvez appliquer avant et pendant un travail d'ingestion important. Utilisez-les avec les métriques de votre propre cluster, car la taille des documents, les analyseurs, le stockage et le nombre de répliques peuvent modifier le résultat.

Comprendre le processus d'indexation

Avant de plonger dans l'optimisation, il est essentiel de comprendre comment Elasticsearch gère l'indexation. Lorsqu'un document est indexé, Elasticsearch effectue plusieurs opérations : analyser le document, analyser les champs (tokenisation, racinisation, etc.), puis stocker l'index inversé et d'autres structures de données. Ces opérations, en particulier l'analyse et les entrées/sorties disque, sont intensives en CPU et en E/S. Dans un environnement distribué, ces opérations sont gérées par des nœuds individuels, ce qui rend la configuration à l'échelle du cluster et les ressources des nœuds cruciales.

Facteurs clés influençant la vitesse d'indexation

Plusieurs facteurs peuvent avoir un impact significatif sur la rapidité avec laquelle Elasticsearch peut indexer des documents :

  • Ressources matérielles : Le CPU, la RAM et surtout la vitesse des E/S disque sont primordiales. Les SSD sont fortement recommandés par rapport aux HDD pour leurs performances de lecture/écriture supérieures.
  • Configuration du cluster : L'allocation des shards, les paramètres de réplication et les rôles des nœuds jouent un rôle.
  • Stratégie d'indexation : La méthode utilisée pour envoyer les données (par exemple, requêtes de documents individuelles vs API bulk).
  • Mapping et types de données : Comment vos champs sont définis et leurs types de données correspondants.
  • Intervalle de rafraîchissement : La fréquence à laquelle les données deviennent visibles pour la recherche.
  • Paramètres du translog : Paramètres de durabilité pour les écritures acquittées.

Optimisation des performances d'indexation : bonnes pratiques

Cette section couvre les stratégies actionnables pour améliorer votre débit d'indexation Elasticsearch.

1. Exploitez l'API Bulk

L'optimisation la plus fondamentale pour l'indexation est d'utiliser l'API Bulk. Au lieu d'envoyer des requêtes d'indexation individuelles, qui entraînent une surcharge réseau et un coût de traitement par requête, l'API Bulk vous permet d'envoyer une liste d'opérations (index, create, update, delete) dans une seule requête HTTP. Cela réduit considérablement la latence réseau et améliore le débit global.

Bonnes pratiques pour l'API Bulk :

  • Taille du lot : Expérimentez avec les tailles de lots. Commencez par des charges utiles modestes, puis augmentez tout en surveillant la latence d'indexation, la pression mémoire et les rejets 429. Le nombre de documents seul ne suffit pas car un document peut être minuscule et un autre peut faire plusieurs mégaoctets.
  • Concurrence : Utilisez plusieurs threads ou des clients asynchrones pour envoyer des requêtes groupées simultanément. Cependant, évitez de submerger votre cluster. Surveillez l'utilisation du CPU et des E/S pour trouver le point idéal.
  • Gestion des erreurs : Implémentez une gestion robuste des erreurs. L'API Bulk renvoie un tableau de réponses, et vous devez vérifier le statut de chaque opération.

Exemple de requête Bulk :

{ "index": { "_index": "my-index", "_id": "1" } }
{ "field1": "value1", "field2": "value2" }
{ "index": { "_index": "my-index", "_id": "2" } }
{ "field1": "value3", "field2": "value4" }

2. Ajustez les paramètres d'indexation

Elasticsearch fournit plusieurs paramètres qui peuvent être ajustés pour optimiser le processus d'indexation. Ceux-ci sont généralement définis par index.

Intervalle de rafraîchissement (index.refresh_interval)

L'intervalle de rafraîchissement contrôle la fréquence à laquelle les données deviennent visibles pour la recherche. Généralement, les index actifs se rafraîchissent environ une fois par seconde lorsqu'ils sont recherchés, mais les valeurs par défaut peuvent varier selon la version et le type d'index. Lors d'une indexation intensive, vous pouvez augmenter cet intervalle pour réduire le travail de rafraîchissement. Le définir sur -1 désactive les rafraîchissements automatiques, ce qui signifie que les données ne deviendront pas consultables jusqu'à ce que vous rafraîchissiez manuellement ou restauriez les rafraîchissements automatiques.

  • Recommandation : Pour les opérations d'indexation groupée, augmentez temporairement index.refresh_interval ou définissez-le sur -1 lorsque la fraîcheur de la recherche n'est pas requise. Une fois l'opération groupée terminée, restaurez le paramètre que vous utilisez pour le comportement de recherche normal et exécutez un rafraîchissement manuel si nécessaire.

Exemple utilisant l'API Index Settings :

# Désactiver temporairement le rafraîchissement
PUT /my-index/_settings
{
  "index" : {
    "refresh_interval" : "-1"
  }
}

# ... effectuer l'indexation groupée ...

# Réactiver le rafraîchissement
PUT /my-index/_settings
{
  "index" : {
    "refresh_interval" : "1s"
  }
}

Durabilité du translog (index.translog.durability)

Le translog est un journal d'écriture anticipée qui garantit la durabilité des données. Il peut être défini sur request (par défaut) ou async. Le définir sur async vide le translog de manière asynchrone, ce qui peut améliorer la vitesse d'indexation mais comporte un léger risque de perte de données si un nœud tombe en panne avant que le translog ne soit écrit sur le disque.

  • Recommandation : Pour les scénarios d'importation groupée où la durabilité est moins critique que la vitesse, async peut être bénéfique. Tenez toujours compte de la tolérance de votre application à la perte de données.

Nombre de répliques (index.number_of_replicas)

Les répliques sont des copies de vos shards primaires, utilisées pour la haute disponibilité et la mise à l'échelle des lectures. Cependant, chaque réplique doit traiter chaque opération d'indexation. Lors des chargements de données initiaux importants, définir index.number_of_replicas sur 0 peut considérablement accélérer l'indexation. Une fois les données chargées, vous pouvez augmenter le nombre de répliques.

Exemple lors d'un chargement groupé :

# Définir temporairement les répliques à 0
PUT /my-index/_settings
{
  "index" : {
    "number_of_replicas" : "0"
  }
}

# ... effectuer l'indexation groupée ...

# Restaurer les répliques (par exemple, à 1)
PUT /my-index/_settings
{
  "index" : {
    "number_of_replicas" : "1"
  }
}

3. Optimisez les mappings

Les mappings définissent comment les documents et leurs champs sont stockés et indexés. Des mappings mal conçus peuvent entraîner des problèmes de performances.

  • Évitez le mapping dynamique pour les grands ensembles de données : Bien que pratique, le mapping dynamique peut entraîner des explosions de mapping et des types de champs inattendus. Définissez des mappings explicites pour vos index, en particulier pour les données à volume élevé.
  • Choisissez des types de données appropriés : Utilisez les types de données les plus efficaces. Par exemple, keyword est plus efficace pour la correspondance de valeurs exactes que text si la recherche en texte intégral n'est pas requise.
  • Désactivez les fonctionnalités inutiles : Si vous n'avez pas besoin de fonctionnalités comme norms pour un champ spécifique (par exemple, pour les correspondances exactes ou les agrégations), les désactiver peut économiser de l'espace et améliorer la vitesse d'indexation (norms: false). De même, désactivez doc_values si nécessaire pour le tri ou les agrégations sur un champ. Cependant, doc_values sont généralement bénéfiques pour les agrégations et le tri, c'est donc une décision nuancée.
  • Champ _source : Si vous n'avez pas besoin du document JSON original, la désactivation de _source peut économiser de l'espace disque et certaines E/S, mais cela empêche la réindexation et rend le débogage plus difficile. Envisagez la compression _source si vous le laissez activé.

Exemple de mapping (avec types explicites et normes désactivées) :

PUT /my-index
{
  "mappings": {
    "properties": {
      "timestamp": {"type": "date"},
      "message": {"type": "text", "norms": false},
      "user_id": {"type": "keyword"}
    }
  }
}

4. Considérations matérielles et d'infrastructure

Même avec des configurations logicielles parfaites, un matériel inadéquat limitera la vitesse d'indexation.

  • E/S disque : Utilisez des SSD rapides. Les SSD NVMe offrent les meilleures performances. Évitez si possible le stockage en réseau (NAS) pour les nœuds d'indexation.
  • CPU et RAM : Des cœurs CPU suffisants sont nécessaires pour l'analyse, et une RAM abondante aide à la mise en cache et aux performances globales de la JVM.
  • Capacité d'ingestion et de coordination : Pour des taux d'ingestion très élevés, envisagez des nœuds d'ingestion dédiés pour les pipelines ou des nœuds de coordination pour le trafic bulk des clients. Les nœuds de données effectuent toujours le travail d'indexation réel, donc ne les privez pas de CPU, de mémoire ou d'E/S disque.
  • Réseau : Assurez une bande passante suffisante et une faible latence entre vos clients et les nœuds Elasticsearch, et entre les nœuds du cluster.

5. Taille et nombre de shards

Bien qu'il ne s'agisse pas directement d'un paramètre d'indexation, le nombre et la taille des shards ont un impact sur les performances. Trop de petits shards peuvent augmenter la surcharge. À l'inverse, un seul shard massif peut être difficile à gérer et peut ne pas bien passer à l'échelle. Visez des tailles de shard entre 10 Go et 50 Go pour des performances optimales, mais cela peut varier.

  • Recommandation : Planifiez votre nombre de shards primaires avant d'indexer de grandes quantités de données. Il n'est généralement pas recommandé de modifier le nombre de shards primaires sur un index existant sans réindexation.

6. Gestion du cycle de vie des index (ILM)

Pour les données de séries temporelles, l'utilisation de la gestion du cycle de vie des index (ILM) est cruciale. Bien que l'ILM aide principalement à gérer les index au fil du temps (rollover, shrink, delete), l'action de rollover peut être configurée pour créer de nouveaux index en fonction de la taille ou de l'âge. Cela garantit que les index restent dans des plages de taille optimales, ce qui profite indirectement aux performances d'indexation.

  • Rollover : Lorsqu'un index atteint une certaine taille ou un certain âge, l'ILM peut automatiquement créer un nouvel index vide et basculer l'alias du flux de données vers celui-ci. Cela vous permet d'optimiser les paramètres du nouvel index (par exemple, réduire les répliques lors du chargement groupé initial) et de maintenir les index actifs gérables.

En pratique

Commencez par l'indexation groupée, des mappings explicites et suffisamment d'E/S disque. Pour les chargements uniques, assouplissez les rafraîchissements et les répliques uniquement lorsque vous pouvez tolérer une fraîcheur de recherche ou une redondance réduite, puis restaurez les paramètres normaux et vérifiez la santé du cluster. Continuez à tester avec vos documents réels ; les tailles de lots et les nombres de shards génériques ne sont que des points de départ.