Leitfaden zur Elasticsearch-Indexierungsleistung: Best Practices enthüllt

Verbessern Sie die Elasticsearch-Indexierung mit Bulk-Anfragen, Refresh- und Replica-Tuning, Mapping-Entscheidungen, Hardware-Checks und Shard-Planung.

Leitfaden zur Elasticsearch-Indexierungsleistung: Best Practices enthüllt

Die Leistung der Elasticsearch-Indexierung wird sichtbar, wenn Ihre Ingest-Pipeline ins Stocken gerät, Bulk-Anfragen abgelehnt werden oder Suchvorgänge bei starken Schreibvorgängen langsamer werden. Die Lösung ist selten eine einzige magische Einstellung; Sie müssen Anfragegröße, Refresh-Verhalten, Mappings, Shard-Layout und Hardware gemeinsam abstimmen.

Dieser Leitfaden konzentriert sich auf praktische Überprüfungen der Elasticsearch-Indexierungsleistung, die Sie vor und während eines großen Ingest-Jobs anwenden können. Verwenden Sie sie mit Metriken aus Ihrem eigenen Cluster, da Dokumentgröße, Analyzer, Speicher und Replica-Anzahl das Ergebnis verändern können.

Den Indexierungsprozess verstehen

Bevor wir uns mit der Optimierung befassen, ist es wichtig zu verstehen, wie Elasticsearch die Indexierung handhabt. Wenn ein Dokument indiziert wird, führt Elasticsearch mehrere Operationen durch: Parsen des Dokuments, Analysieren der Felder (Tokenisierung, Stemming usw.) und anschließendes Speichern des invertierten Index und anderer Datenstrukturen. Diese Operationen, insbesondere die Analyse und der Festplatten-I/O, sind CPU- und I/O-intensiv. In einer verteilten Umgebung werden diese Operationen von einzelnen Knoten ausgeführt, was die clusterweite Konfiguration und die Knotenressourcen entscheidend macht.

Schlüsselfaktoren, die die Indexierungsgeschwindigkeit beeinflussen

Mehrere Faktoren können erheblichen Einfluss darauf haben, wie schnell Elasticsearch Dokumente indizieren kann:

  • Hardware-Ressourcen: CPU, RAM und insbesondere die Festplatten-I/O-Geschwindigkeit sind von größter Bedeutung. SSDs werden aufgrund ihrer überlegenen Lese-/Schreibleistung gegenüber HDDs dringend empfohlen.
  • Cluster-Konfiguration: Shard-Zuweisung, Replikationseinstellungen und Knotenrollen spielen eine Rolle.
  • Indexierungsstrategie: Die Methode zum Senden von Daten (z. B. einzelne Dokumentanfragen vs. Bulk-API).
  • Mapping und Datentypen: Wie Ihre Felder definiert sind und ihre entsprechenden Datentypen.
  • Refresh-Intervall: Wie oft Daten für die Suche sichtbar werden.
  • Translog-Einstellungen: Dauerhaftigkeitseinstellungen für bestätigte Schreibvorgänge.

Optimierung der Indexierungsleistung: Best Practices

Dieser Abschnitt behandelt umsetzbare Strategien zur Verbesserung Ihres Elasticsearch-Indexierungsdurchsatzes.

1. Nutzen Sie die Bulk-API

Die grundlegendste Optimierung für die Indexierung ist die Verwendung der Bulk-API. Anstatt einzelne Indexierungsanfragen zu senden, die Netzwerk-Overhead und Verarbeitungskosten pro Anfrage verursachen, ermöglicht die Bulk-API das Senden einer Liste von Operationen (Index, Erstellen, Aktualisieren, Löschen) in einer einzigen HTTP-Anfrage. Dies reduziert die Netzwerklatenz erheblich und verbessert den Gesamtdurchsatz.

Best Practices für die Bulk-API:

  • Batch-Größe: Experimentieren Sie mit Batch-Größen. Beginnen Sie mit kleinen Nutzlasten und erhöhen Sie diese dann, während Sie die Indexierungslatenz, den Speicherdruck und 429-Ablehnungen beobachten. Die reine Dokumentanzahl reicht nicht aus, da ein Dokument winzig und ein anderes mehrere Megabyte groß sein kann.
  • Parallelität: Verwenden Sie mehrere Threads oder asynchrone Clients, um Bulk-Anfragen parallel zu senden. Vermeiden Sie jedoch, Ihren Cluster zu überlasten. Überwachen Sie CPU- und I/O-Auslastung, um den optimalen Punkt zu finden.
  • Fehlerbehandlung: Implementieren Sie eine robuste Fehlerbehandlung. Die Bulk-API gibt ein Array von Antworten zurück, und Sie müssen den Status jeder Operation überprüfen.

Beispiel für eine Bulk-Anfrage:

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

2. Indexierungseinstellungen optimieren

Elasticsearch bietet mehrere Einstellungen, die zur Optimierung des Indexierungsprozesses angepasst werden können. Diese werden in der Regel pro Index festgelegt.

Refresh-Intervall (index.refresh_interval)

Das Refresh-Intervall steuert, wie oft Daten für die Suche sichtbar werden. Üblicherweise aktualisieren aktive Indizes etwa einmal pro Sekunde, wenn sie durchsucht werden, aber die Standardwerte können je nach Version und Indextyp variieren. Während starker Indexierung können Sie dieses Intervall erhöhen, um die Refresh-Arbeit zu reduzieren. Wenn Sie es auf -1 setzen, werden automatische Aktualisierungen deaktiviert, was bedeutet, dass Daten erst durchsuchbar werden, wenn Sie manuell aktualisieren oder die automatischen Aktualisierungen wiederherstellen.

  • Empfehlung: Erhöhen Sie bei Bulk-Indexierungsvorgängen vorübergehend index.refresh_interval oder setzen Sie es auf -1, wenn Suchaktualität nicht erforderlich ist. Nach Abschluss des Bulk-Vorgangs stellen Sie die Einstellung wieder her, die Sie für das normale Suchverhalten verwenden, und führen Sie bei Bedarf eine manuelle Aktualisierung durch.

Beispiel mit der Index-Einstellungen-API:

# Refresh vorübergehend deaktivieren
PUT /my-index/_settings
{
  "index" : {
    "refresh_interval" : "-1"
  }
}

# ... Bulk-Indexierung durchführen ...

# Refresh wieder aktivieren
PUT /my-index/_settings
{
  "index" : {
    "refresh_interval" : "1s"
  }
}

Translog-Dauerhaftigkeit (index.translog.durability)

Das Translog ist ein Write-Ahead-Protokoll, das die Datendauerhaftigkeit gewährleistet. Es kann auf request (Standard) oder async gesetzt werden. Die Einstellung auf async spült das Translog asynchron, was die Indexierungsgeschwindigkeit verbessern kann, aber ein geringes Risiko von Datenverlust birgt, wenn ein Knoten ausfällt, bevor das Translog auf die Festplatte geschrieben wurde.

  • Empfehlung: Für Bulk-Import-Szenarien, bei denen die Dauerhaftigkeit weniger kritisch ist als die Geschwindigkeit, kann async vorteilhaft sein. Berücksichtigen Sie immer die Toleranz Ihrer Anwendung gegenüber Datenverlust.

Anzahl der Replicas (index.number_of_replicas)

Replicas sind Kopien Ihrer primären Shards, die für Hochverfügbarkeit und Leseskalierung verwendet werden. Jedes Replica muss jedoch jeden Indexierungsvorgang verarbeiten. Während anfänglicher großer Datenladungen kann das Setzen von index.number_of_replicas auf 0 die Indexierung erheblich beschleunigen. Nachdem die Daten geladen sind, können Sie die Replica-Anzahl erhöhen.

Beispiel während des Bulk-Ladens:

# Replicas vorübergehend auf 0 setzen
PUT /my-index/_settings
{
  "index" : {
    "number_of_replicas" : "0"
  }
}

# ... Bulk-Indexierung durchführen ...

# Replicas wiederherstellen (z. B. auf 1)
PUT /my-index/_settings
{
  "index" : {
    "number_of_replicas" : "1"
  }
}

3. Mappings optimieren

Mappings definieren, wie Dokumente und ihre Felder gespeichert und indiziert werden. Schlecht gestaltete Mappings können zu Leistungsproblemen führen.

  • Vermeiden Sie dynamisches Mapping für große Datensätze: Obwohl praktisch, kann dynamisches Mapping zu Mapping-Explosionen und unerwarteten Feldtypen führen. Definieren Sie explizite Mappings für Ihre Indizes, insbesondere für Daten mit hohem Volumen.
  • Wählen Sie geeignete Datentypen: Verwenden Sie die effizientesten Datentypen. Beispielsweise ist keyword für exakte Wertübereinstimmungen effizienter als text, wenn keine Volltextsuche erforderlich ist.
  • Deaktivieren Sie unnötige Funktionen: Wenn Sie Funktionen wie norms für ein bestimmtes Feld nicht benötigen (z. B. für exakte Übereinstimmungen oder Aggregationen), kann deren Deaktivierung Speicherplatz sparen und die Indexierungsgeschwindigkeit verbessern (norms: false). Deaktivieren Sie ebenso doc_values, wenn sie nicht für Sortierung oder Aggregationen auf einem Feld benötigt werden. Allerdings sind doc_values im Allgemeinen vorteilhaft für Aggregationen und Sortierung, daher ist dies eine nuancierte Entscheidung.
  • _source-Feld: Wenn Sie das ursprüngliche JSON-Dokument nicht benötigen, kann die Deaktivierung von _source Festplattenspeicher und etwas I/O sparen, erschwert jedoch das Reindexing und das Debugging. Erwägen Sie _source-Kompression, wenn Sie es aktiviert lassen.

Beispiel-Mapping (mit expliziten Typen und deaktivierten Normen):

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

4. Hardware- und Infrastrukturüberlegungen

Selbst bei perfekten Softwarekonfigurationen wird unzureichende Hardware die Indexierungsgeschwindigkeit begrenzen.

  • Festplatten-I/O: Verwenden Sie schnelle SSDs. NVMe-SSDs bieten die beste Leistung. Vermeiden Sie nach Möglichkeit Network Attached Storage (NAS) für Indexierungsknoten.
  • CPU und RAM: Ausreichend CPU-Kerne sind für die Analyse erforderlich, und reichlich RAM hilft beim Caching und der allgemeinen JVM-Leistung.
  • Ingest- und Koordinierungskapazität: Für sehr hohe Aufnahmeraten sollten Sie dedizierte Ingest-Knoten für Pipelines oder Koordinierungsknoten für den Client-Bulk-Verkehr in Betracht ziehen. Datenknoten erledigen weiterhin die eigentliche Indexierungsarbeit, also lassen Sie sie nicht ohne CPU, Speicher oder Festplatten-I/O.
  • Netzwerk: Stellen Sie ausreichende Bandbreite und geringe Latenz zwischen Ihren Clients und Elasticsearch-Knoten sowie zwischen den Knoten im Cluster sicher.

5. Shard-Größe und -Anzahl

Obwohl keine direkte Indexierungseinstellung, wirken sich Anzahl und Größe der Shards auf die Leistung aus. Zu viele kleine Shards können den Overhead erhöhen. Umgekehrt kann ein einzelner massiver Shard schwer zu verwalten sein und möglicherweise nicht gut skalieren. Streben Sie für optimale Leistung Shard-Größen zwischen 10 GB und 50 GB an, aber dies kann variieren.

  • Empfehlung: Planen Sie Ihre primäre Shard-Anzahl, bevor Sie große Datenmengen indizieren. Es wird generell nicht empfohlen, die Anzahl der primären Shards auf einem vorhandenen Index ohne Reindexing zu ändern.

6. Index Lifecycle Management (ILM)

Für Zeitreihendaten ist die Verwendung von Index Lifecycle Management (ILM) entscheidend. Während ILM hauptsächlich bei der Verwaltung von Indizes im Laufe der Zeit hilft (Rollover, Shrink, Delete), kann die Rollover-Aktion so konfiguriert werden, dass basierend auf Größe oder Alter neue Indizes erstellt werden. Dies stellt sicher, dass Indizes innerhalb optimaler Größenbereiche bleiben, was indirekt der Indexierungsleistung zugutekommt.

  • Rollover: Wenn ein Index eine bestimmte Größe oder ein bestimmtes Alter erreicht, kann ILM automatisch einen neuen, leeren Index erstellen und den Datenstrom-Alias darauf umschalten. Dies ermöglicht es Ihnen, Einstellungen für den neuen Index zu optimieren (z. B. niedrigere Replicas während des anfänglichen Bulk-Ladens) und aktive Indizes handhabbar zu halten.

Praktische Erkenntnisse

Beginnen Sie mit Bulk-Indexierung, expliziten Mappings und ausreichend Festplatten-I/O. Lockern Sie bei einmaligen Ladevorgängen Refreshes und Replicas nur, solange Sie eine reduzierte Suchaktualität oder Redundanz tolerieren können, und stellen Sie dann die normalen Einstellungen wieder her und überprüfen Sie die Cluster-Gesundheit. Testen Sie weiterhin mit Ihren echten Dokumenten; generische Batch-Größen und Shard-Anzahlen sind nur Ausgangspunkte.