ES|QL Joins sind da! Jawohl, Joins!

Elasticsearch 8.18 enthält den ES|QL-Befehl LOOKUP JOIN, unseren ersten JOIN im SQL-Stil.

Elasticsearch 8.18 enthält unser erstes SQL-ähnliches JOIN: ES|QLs LOOKUP-JOIN-Befehl. Es ist jetzt in der Tech-Vorschau verfügbar und ermöglicht Datenkorrelation und -anreicherung mit leicht aktualisierbaren Lookup-Datensätzen. Müssen Sie Host- und Asset-Informationen zu Ihren Events hinzufügen? Kein Problem. Möchten Sie überprüfen, welche IP-Adressen oder URLs auf Bedrohungslisten stehen? Klar! Aktualisieren Sie den Lookup-Datensatz und verwenden Sie ihn sofort? Go for it!

Lookup Join ist ein SQL-ähnliches LEFT OUTER JOIN, das auf einem neuen Indexmodus namens
Lookup für die rechte Seite basiert. Der Lookup-Index könnte Vermögenswerte, Bedrohungsdaten wie bekannte unsichere IP-Adressen, Bestellinformationen, Mitarbeiter- oder Kundendaten es gibt unendlich viele Möglichkeiten.

Suche nach der rechten Seite

Elasticsearch bot bisher keine Join-Funktionalität, obwohl im Laufe der Zeit einige Ansätze in diese Richtung verfolgt wurden, wie beispielsweise verschachtelte und übergeordnete Join-Feldtypen sowie die Anreicherung von Daten. Üblicherweise wurde die Denormalisierung von Daten durch die Speicherung der Referenzdaten neben den Ereignissen im selben Index oder durch clientseitige Joins gefördert. Diese Lösungen beeinträchtigen jedoch die Skalierbarkeit bei größeren Datenmengen und können bei einer hohen Datenvielfalt und unterschiedlichen Anwendungsfällen einschränkend wirken. Es ist an der Zeit, dass Elasticsearch Joins unterstützt. Und jetzt ist es möglich: ES|QL ist nicht nur eine Sprache sie basiert auf einer neuen Compute-Engine. Die ES|QL-Engine ermöglicht fortgeschrittene Features wie Joins.

Um Lookup-Joins zu ermöglichen, haben wir einen neuen Indexmodus erstellt: lookup. Ein Lookup-Index ähnelt weitgehend einem regulären Index (mode:standard ist der Standard), d. h. er ist direkt aktualisierbar. Der Hauptunterschied besteht darin, dass ein Lookup-Index nur aus einem Shard besteht. Daher ist er auf 2 Milliarden Dokumente begrenzt – ein Lucene-Limit für einen Shard. Dies sollte für viele Anwendungsfälle von Lookup-Joins mehr als ausreichend sein, um die Daten der „rechten Seite“ zu speichern. Durch diese Begrenzung vermeiden wir einige Probleme, die bei vollständig verteilten Joins auftreten können, indem wir die Kardinalität der Quelldaten auf der rechten Seite des Joins reduzieren. Außerdem erfahren wir so, welche Datensätze Sie als Lookup-Referenzen verwenden möchten, um diese zukünftig zu optimieren. 

Abgesehen vom Lookup-Index-Modus gibt es keine Einschränkungen für die Quelldaten und keine Datenvorbereitung, die für einen Join erforderlich ist. Das heißt, es ist einfach, Suchdatensätze hinzuzufügen und sie auf dem neuesten Stand zu halten. 

Ein Teil davon war bereits mit dem Kommando ENRICH in ES|QL möglich. ENRICH wurde für Ingest-Zeit-Lookups in Ingest-Pipelines und für kleine Datensätze, die sich nicht oft ändern, optimiert, daher war es zwar praktisch, aber nicht ideal. Lookup Join ist einfacher einzurichten und zu verwalten als ENRICH: 

  • Es müssen keine Anreicherungsrichtlinien erstellt werden

  • Keine Umsetzung der Richtlinien

  • Nachschlageindizes sind beschreibbar

  • Es gibt weniger Kopien der Daten

  • Bessere Handhabung mehrerer Treffer – während enrich mehrwertige Felder erzeugt, wenn mehrere Treffer vorliegen, erzeugt lookup join mehrere Zeilen. Dadurch wird es einfacher, weitere Analysen wie Gruppierung und Aggregation durchzuführen, beispielsweise die pro Nutzer übertragenen Bytes oder die Bestellsummen.

  • Lookup Join ermöglicht die spontane Spezifizierung des Match-Felds

Hier sind nur einige Beispiele, wie Sie LOOKUP JOIN verwenden könnten: 

  • Verbinden Sie Sicherheitsereignis mit Bedrohungsdaten, um eine Veranstaltung noch bereichernd zu gestalten.

  • Meine aktuellen Hosts im Vergleich zu den neuesten Bedrohungsinformationen oder internen Metadaten abfragen

  • Korrelieren Sie IOT-Messungen mit statischen oder dynamischen Metadaten (Hersteller, Volumeneinheit)

  • Sicherheitsereignisse mit Hostinformationen verknüpfen, um mehr Kontext und Filtermöglichkeiten zu erhalten.

  • Fügen Sie einige Fakten hinzu, wie z. B. die Kritikalität der Anlage (dieser Nutzer ist eine Führungskraft).

  • Fügen Sie CrowdStrike-A.I.D.s zu einer Quelle hinzu, die Hostnamen enthält.

  • Prüfen Sie, ob bestimmte IP-Adressen in Bedrohungsdatenfeeds enthalten sind.

  • Mitarbeiterinformationen zu Veranstaltungen hinzufügen

Die Möglichkeiten sind endlos.

Beispielverwendung

Schauen wir uns einige reale Beispiele an, um zu sehen, wie einfach und mächtig das sein kann. 

Als SRE müssen Sie möglicherweise:

  • Füge den Protokollen eine Umgebung basierend auf der IP-Adresse oder dem Hostnamen hinzu.

  • Mitarbeiterinformationen mit Protokollen verknüpfen

  • Finde heraus, welches Team einen Server besitzt

Vor LOOKUP JOIN mussten Sie Folgendes tun: 

  1. Fügen Sie Ihre Referenzdaten (Umgebungen) in einen Index ein

  2. Definieren Sie eine Anreicherungsrichtlinie basierend auf diesem Index und geben Sie dabei den Richtlinientyp, das Übereinstimmungsfeld und die Anreicherungsfelder an.

  3. Führen Sie die Anreicherungsrichtlinie einmal aus, um den Anreicherungsindex zu erstellen.

  4. Wiederholen Sie dies für jeden Referenzdatensatz (Mitarbeiter, Teams).

  5. Anreicherungsrichtlinie ausführen, sobald sich die Daten ändern

Mit LOOKUP JOIN fügen Sie einfach die Referenzdaten in einen LOOKUP-Index ein und schon kann es losgehen! 

Stellen Sie sich vor, Sie erhalten eine Benachrichtigung, dass bei einigen Nutzern Fehler auf Ihrer E-Commerce-Website auftreten. Sie finden Weblogs, in denen die Antwort nicht dem HTTP-Antwortcode 200 für Erfolg entspricht. Man möchte diese nach Umgebung aufschlüsseln, um zu sehen, ob Produktionskunden betroffen sind, aber die Logs haben kein Umgebungsfeld. Das ist in Ordnung – fügen Sie einfach einen Lookup-Join für die Umgebung hinzu, beispielsweise mithilfe einer Datei wie dieser:

clientip,environment
192.168.1.9,QA
192.168.14.2,Dev
192.168.12.3,Prod
…

Fügen Sie nun den LOOKUP JOIN auf dem Umgebungs-Lookup-Index hinzu (meiner heißt envs_lkp):

FROM kibana_sample_data_logs | WHERE response.keyword != "200" 
| LOOKUP JOIN envs_lkp ON clientip 
| STATS COUNT(*) by response, environment
LOOKUP JOIN

Es gibt Fehler in der Produktion und der Qualitätssicherung. Wir können eine Liste der Teams, denen die einzelnen Webserver gehören, einsehen, um herauszufinden, wen wir kontaktieren sollten:

host,team
www.elastic.co,Web team
artifacts.elastic.co,Delivery team
cdn.elastic-elastic-elastic.org,Cloud team
elastic-elastic-elastic.org,Web team
FROM kibana_sample_data_logs | WHERE response.keyword != "200"
| LOOKUP JOIN teams_lkp ON host
| STATS num = COUNT(*) by host, response.keyword, team
| SORT num DESC
Liste der Teambesitzer

Security-Analysten lieben ihre Joins! Vielleicht wollen sie:

  • Identifizieren Sie Client-IPs, die bekannte fehlerhafte URLs anfordern

  • Informationen mit den Anlagen korrelieren, um Ereignisse zu gruppieren und Prioritäten oder Risiken zuzuweisen.

Sie könnten eine Liste schädlicher URLs von URLhaus auf Abuse.ch herunterladen und in einen Suchindex hochladen.

FROM logs 
| LOOKUP JOIN urlhaus_lkp ON url 
| WHERE threat IS NOT NULL 
| KEEP @timestamp, url.keyword, clientip, threat
Liste der bösartigen URLs herunterladen

So erstellen Sie Suchvorgänge

Sie benötigen mindestens einen Lookup-Index, um Lookup-Join zu verwenden. Wir arbeiten an Möglichkeiten, das Erstellen und Aktualisieren von Lookups in Kibana zu vereinfachen. Bis dahin können Sie auf verschiedene Arten einen Lookup-Index erstellen – wichtig ist dabei, dass der Indexmodus auf „Lookup“ eingestellt ist.

Suchindex mithilfe der Indexverwaltung erstellen

Klicken Sie im linken Navigationsbereich von Kibana auf Stack Management, und anschließend „Indexverwaltung“. Klicken Sie auf der rechten Seite auf „Index erstellen“.

Suchindex mithilfe der Indexverwaltung erstellen

Geben Sie einen Indexnamen an und wählen Sie im Dropdown-Menü „Indexmodus“ die Option „Nachschlagen“ aus:

Geben Sie einen Indexnamen an

Klicken Sie auf Erstellen, um einen leeren Lookup-Index zu erstellen. 

Nachschlageindex über APIs erstellen

Erstellen Sie einen Lookup-Index mit der Create-Index-API – achten Sie nur darauf, den Indexmodus einzubeziehen:

PUT mylookupindex
{
 "settings": {
   "index.mode": "lookup"
 }
}

Lookup-Index mit dem ML-Datei-Uploader erstellen

Im linken Navigationsfenster von Kibana auf Machine Learning und dann auf File Data Visualizer (oder geben Sie „hochladen" in Kibanas Suchleiste ein).

Data Visualizer

Wählen Sie Ihre Datei aus oder ziehen Sie sie per Drag-and-Drop – CSV eignet sich dafür gut.

Nachdem Sie auf „Importieren“geklickt haben, geben Sie einen Namen für den Index ein und klicken Sie auf „Erweitert“, um die Indexeinstellungen anzuzeigen. Hier sollten Sie die Option „index.mode: lookup“ hinzufügen.

Fortgeschritten

Schließen Sie den Datei-Upload ab, indem Sie auf Importklicken. Ein Index und eine Data view werden erstellt. 

In allen Fällen können Sie jetzt den Lookup-Index in Ihren ES|QL-Anfragen referenzieren.

Antworten auf häufig gestellte Fragen

Q: Wann sollte ich keine Joins verwenden?
Lookup-Join ist wirklich mächtig, aber mit großer Kraft … Nun, Sie wissen schon. Joins können eine teure Operation sein, und jeder Join fügt Ihrer Abfrage etwas Latenz hinzu. Es kann trotzdem Szenarien geben, in denen ein Join übertrieben oder nicht die beste Option ist. Wenn es zum Beispiel ein Feld gibt, das Sie sehr häufig in viele Abfragen einbinden, sollten Sie in Erwägung ziehen, es in den linken Index zu denormalisieren. Fügen Sie es zur Ingest-Zeit mit einem Enrich-Ingest-Prozessor, File-Übermittler-Konfiguration, verwenden Sie einen Logstash-Filter usw. Diese einmalige Eingabeverarbeitung ist ein Kompromiss für eine leichte Erhöhung der Speichernutzung zugunsten schnellerer Abfragen. Dies wäre am besten für Referenzwerte anwendbar, die sich nicht häufig ändern (der Nutzername einer Nutzer-ID) oder nie ändern (der Hersteller eines Hosts).

Q: Kann ich eine Abfrage direkt abfragen?
Ja! Ein Lookup-Index ist meist „nur ein Index“, sodass man ihn mit ES|QL abfragen kann.

FROM <lookup_index> | …

Oder erstellen Sie eine Data View. 

Data view erstellen

F: Kann ich Daten von Logstash oder Agent senden?
Ja! Denken Sie nur daran, dass ein Lookup-Index kein Datenstream ist, und es nur ein Shard ist, sodass Sie „nur“ bis zu 2 Milliarden Dokumente an jeden Lookup-Index senden können.

Was kommt als Nächstes?

Wir arbeiten daran, einige bekannte Einschränkungen zu beseitigen, damit der Lookup-Join allgemein verfügbar werden kann. Darüber hinaus entwickeln wir ein erstklassiges Bearbeitungserlebnis für die Nachschlagedatensätze. Stellen Sie sich vor, Sie könnten Lookup-Indizes direkt in Kibana Discover erstellen und bearbeiten oder eine CSV-Datei auf Discover ablegen, um den Index zu füllen. Hier ist ein Entwurf, wie das aussehen könnte:

Frühes Modell einer möglichen zukünftigen Nutzererlebnis beim Bearbeiten von Suchbegriffen
Frühes Modell einer möglichen zukünftigen Nutzererlebnis beim Bearbeiten von Suchbegriffen

Und Lookup-Joins sind erst der Anfang. Wir möchten weitere nützliche Join-Typen anbieten, wie z. B. INNER Joins oder Unterabfragen, und auch das Verknüpfen mit beliebigen Indizes ermöglichen (nicht nur mit Nachschlageindizes).

Erste Schritte

Das ist also lookup join, verfügbar in Elasticsearch 8.18/9.0 als technische Vorschau. 

 

Bereit loszulegen? Elastic 8.18 und 9.0 sind jetzt verfügbar auf Elastic Cloud – dem gehosteten Elasticsearch Service mit allen neuen Features dieser aktuellen Version. Das ES|QL-Team freut sich auf Ihr Feedback. Nutzen Sie dazu einfachdie Schaltfläche „Feedback senden“ im ES|QL-Editor in Discover. Und übrigens: Wir haben es tatsächlich geschafft, diesen Blogbeitrag ganz ohne Wortspiele mit dem Begriff „Joins“ zu schreiben … vielen Dank fürs Lesen!

 

 

Die Entscheidung über die Veröffentlichung der in diesem Blogeintrag beschriebenen Leistungsmerkmale und Features sowie deren Zeitpunkt liegt allein bei Elastic. Es ist möglich, dass noch nicht verfügbare Leistungsmerkmale oder Features nicht rechtzeitig oder überhaupt nicht veröffentlicht werden.