Die Datenmodellierung in Elasticsearch ist nicht so offensichtlich wie bei relationalen Datenbanken. Im Gegensatz zu herkömmlichen relationalen Datenbanken, die auf Datennormalisierung und SQL-Joins basieren, erfordert Elasticsearch alternative Ansätze zur Verwaltung von Beziehungen.
Es gibt vier gängige Workarounds zum Verwalten von Beziehungen in Elasticsearch:
Anwendungsseitige Verknüpfungen
Datendenormalisierung
Verschachtelte Feldtypen und verschachtelte Abfragen
Eltern-Kind-Beziehungen
In diesem Blog besprechen wir, wie Sie Ihr Datenmodell so gestalten können, dass es Beziehungen mithilfe des verschachtelten Feldtyps und Eltern-Kind-Beziehungen handhaben kann. Wir behandeln die Architektur, Leistungsauswirkungen und Anwendungsfälle für diese beiden Techniken.
Elasticsearch unterstützt verschachtelte Strukturen, in denen Objekte andere Objekte enthalten können. Verschachtelte Feldtypen sind JSON-Objekte im Hauptdokument, die ihre eigenen unterschiedlichen Felder und Typen haben können. Diese verschachtelten Objekte werden als separate, versteckte Dokumente behandelt, auf die nur über eine verschachtelte Abfrage zugegriffen werden kann.
Verschachtelte Feldtypen eignen sich gut für Beziehungen, bei denen Datenintegrität, enge Kopplung und hierarchische Struktur wichtig sind. Dazu gehören Eins-zu-eins- und Eins-zu-viele-Beziehungen, bei denen es eine Hauptentität gibt. Beispielsweise die Darstellung einer Person und ihrer mehreren Adressen und Telefonnummern in einem einzigen Dokument.
Bei verschachtelten Feldtypen speichert Elasticsearch das gesamte Dokument sowie übergeordnete und verschachtelte Objekte in einem einzigen Lucene-Block und -Segment. Dies kann zu schnelleren Abfragegeschwindigkeiten führen, da die Beziehung auf ein Dokument beschränkt ist.
Sehen wir uns das Beispiel eines Blogbeitrags mit Kommentaren an. Wir möchten die Kommentare unter dem Blogbeitrag verschachteln, damit sie im selben Dokument problemlos gemeinsam abgefragt werden können.
{ "post_id": "1", "title": "Introduction to Elasticsearch Data Modeling", "content": "Exploring various data modeling options in Elasticsearch.", "comments": [ { "comment_id": "101", "text": "Great overview of data modeling!" }, { "comment_id": "102", "text": "Looking forward to more content." } ] }
Zu den Vorteilen verschachtelter Objektbeziehungen gehören:
Ineffiziente Aktualisierung : Aktualisierungen, Einfügungen und Löschungen in einem beliebigen Teil eines Dokuments mit verschachtelten Objekten erfordern eine Neuindizierung des gesamten Dokuments. Dies kann sehr speicherintensiv sein, insbesondere wenn die Dokumente groß sind oder häufig aktualisiert werden.
Abfrageleistung bei großen verschachtelten Feldern : Wenn Sie Dokumente mit besonders großen verschachtelten Feldern haben, kann dies Auswirkungen auf die Leistung haben. Dies liegt daran, dass die Suchanfrage das gesamte Dokument abruft.
Mehrere Verschachtelungsebenen können komplex werden : Das Ausführen von Abfragen über verschachtelte Strukturen mit mehreren Ebenen kann immer noch komplex werden. Das liegt daran, dass Abfragen verschachtelte Abfragen innerhalb verschachtelter Abfragen enthalten können, was zu weniger lesbarem Code führt.
Bei der Zuordnung von übergeordneten und untergeordneten Dokumenten werden Dokumente in übergeordnete und untergeordnete Typen unterteilt. Jedes untergeordnete Dokument ist direkt mit einem übergeordneten Dokument verknüpft. Diese Beziehung wird durch einen bestimmten Feldwert im untergeordneten Dokument hergestellt, der mit der ID des übergeordneten Dokuments übereinstimmt. Das übergeordnete und untergeordnete Modell verfolgt einen dezentralen Ansatz, bei dem übergeordnete und untergeordnete Dokumente unabhängig voneinander existieren.
Übergeordnete/untergeordnete Verknüpfungen eignen sich für Eins-zu-viele- oder Viele-zu-viele-Beziehungen zwischen Entitäten. Stellen Sie sich eine Anwendung vor, in der Sie Beziehungen zwischen Unternehmen und Kontakten erstellen und nach Unternehmen und Kontakten sowie nach Kontakten bei bestimmten Unternehmen suchen möchten.
Elasticsearch sorgt für leistungsfähige Verknüpfungen von übergeordneten und untergeordneten Elementen, indem es verfolgt, welche übergeordneten Elemente mit welchen untergeordneten Elementen verbunden sind, und indem es dafür sorgt, dass sich beide Entitäten auf demselben Shard befinden. Durch die Lokalisierung des Verknüpfungsvorgangs vermeidet Elasticsearch die Notwendigkeit einer umfangreichen Kommunikation zwischen Shards, die einen Leistungsengpass darstellen kann.
Nehmen wir das Beispiel einer Eltern-Kind-Beziehung für Blogbeiträge und Kommentare. Jeder Blogbeitrag, also der übergeordnete Beitrag, kann mehrere Kommentare, also die untergeordneten Beiträge, haben. Um die Eltern-Kind-Beziehung zu erstellen, indizieren wir die Daten wie folgt:
PUT my-index-000001 { "mappings": { "properties": { "post_id": { "type": "keyword" }, "post_id": { "type": "join", "relations": { "post": "comment" } } } } }
Ein übergeordnetes Dokument wäre ein Beitrag, der wie folgt aussieht:
{ "post_id": "1", "title": "Introduction to Elasticsearch Data Modeling", "content": "Exploring various data modeling options in Elasticsearch." }
Das untergeordnete Dokument wäre dann ein Kommentar, der die Post-ID enthält, die ihn mit seinem übergeordneten Dokument verknüpft.
{ "comment_id": "101", "text": "Great overview of data modeling!", "post_id": "1" }
Zu den Vorteilen der Eltern-Kind-Modellierung gehören:
Ähnelt einem relationalen Datenmodell : In Eltern-Kind-Beziehungen sind die Eltern- und Kinddokumente getrennt und durch eine eindeutige Eltern-ID verknüpft. Diese Konfiguration ähnelt eher einem relationalen Datenbankmodell und kann für diejenigen, die mit solchen Konzepten vertraut sind, intuitiver sein.
Aktualisierungseffizienz : Untergeordnete Dokumente können hinzugefügt, geändert oder gelöscht werden, ohne dass dies Auswirkungen auf das übergeordnete Dokument oder andere untergeordnete Dokumente hat. Dies ist insbesondere dann von Vorteil, wenn Sie mit einer großen Anzahl untergeordneter Dokumente arbeiten, die häufig aktualisiert werden müssen. Beachten Sie, dass die Verknüpfung eines untergeordneten Dokuments mit einem anderen übergeordneten Dokument ein komplexerer Prozess ist, da sich das neue übergeordnete Dokument möglicherweise auf einem anderen Shard befindet.
Besser geeignet für heterogene untergeordnete Dokumente : Da untergeordnete Dokumente separat gespeichert werden, sind sie möglicherweise speicher- und speichereffizienter, insbesondere in Fällen, in denen viele untergeordnete Dokumente erhebliche Größenunterschiede aufweisen.
Zu den Nachteilen von Eltern-Kind-Beziehungen gehören:
Teure, langsame Abfragen : Das Zusammenführen von Dokumenten über verschiedene Indizes hinweg erhöht den Rechenaufwand während der Abfrageausführung, was sich wiederum auf die Leistung auswirkt. Elasticsearch weist darauf hin, dass Eltern-Kind-Abfragen 5-10x langsamer sein können als Abfragen verschachtelter Objekte.
Mapping-Overhead : Über- und Unterbeziehungen können mehr Speicher und Cache-Ressourcen verbrauchen. Elasticsearch verwaltet eine Map der Über- und Unterbeziehungen, die groß werden und viel Speicher verbrauchen kann, insbesondere bei einem großen Dokumentvolumen.
Shard-Größenverwaltung : Da sich sowohl übergeordnete als auch untergeordnete Dokumente auf demselben Shard befinden, besteht das potenzielle Risiko einer ungleichmäßigen Datenverteilung im Cluster. Einige Shards können deutlich größer werden als andere, insbesondere wenn übergeordnete Dokumente viele untergeordnete Dokumente haben. Dies kann zu Herausforderungen bei der Verwaltung und Skalierung des Elasticsearch-Clusters führen.
Neuindizierung und Clusterwartung : Wenn Sie Daten neu indizieren oder die Sharding-Strategie ändern müssen, kann die Eltern-Kind-Beziehung diesen Vorgang erschweren. Sie müssen sicherstellen, dass die Beziehungsintegrität während solcher Vorgänge gewahrt bleibt. Routinemäßige Clusterwartungsaufgaben wie Shard-Neuausgleich oder Knotenupgrades können komplexer werden. Es muss besonders darauf geachtet werden, dass Eltern-Kind-Beziehungen während dieser Prozesse nicht unterbrochen werden.
Elastic , das Unternehmen hinter Elasticsearch, empfiehlt immer, anwendungsseitige Verknüpfungen, Datendenormalisierung und/oder verschachtelte Objekte durchzuführen, bevor Sie sich für Eltern-Kind-Beziehungen entscheiden.
In der nachfolgenden Tabelle finden Sie eine Zusammenfassung der Merkmale verschachtelter Feldtypen und Abfragen sowie Eltern-Kind-Beziehungen, um die Datenmodellierungsansätze nebeneinander vergleichen zu können.
| Verschachtelte Feldtypen und verschachtelte Abfragen | Eltern-Kind-Beziehungen |
---|---|---|
Definition | Verschachtelt ein Objekt in einem anderen Objekt | Verknüpft übergeordnete und untergeordnete Dokumente |
Beziehungen | Eins-zu-eins, eins-zu-viele | Eins-zu-viele, viele-zu-viele |
Abfragegeschwindigkeit | Im Allgemeinen schneller als Eltern-Kind-Beziehungen, da die Daten im selben Block und Segment gespeichert werden | Im Allgemeinen 5–10 Mal langsamer als verschachtelte Objekte, da übergeordnete und untergeordnete Dokumente zum Abfragezeitpunkt zusammengeführt werden. |
Abfrageflexibilität | Weniger flexibel als Parent-Child-Abfragen, da der Umfang der Abfrage auf die Grenzen jedes verschachtelten Objekts beschränkt ist. | Bietet mehr Flexibilität bei der Abfrage, da übergeordnete oder untergeordnete Dokumente gemeinsam oder separat abgefragt werden können |
Datenaktualisierungen | Das Aktualisieren verschachtelter Objekte erforderte die Neuindizierung des gesamten Dokuments | Das Aktualisieren untergeordneter Dokumente ist einfacher, da nicht alle Dokumente neu indiziert werden müssen. |
Management | Einfachere Verwaltung, da alles in einem einzigen Dokument enthalten ist | Komplexere Verwaltung aufgrund separater Indizierung und Pflege der Beziehungen zwischen übergeordneten und untergeordneten Dokumenten |
Anwendungsfälle | Speichern und Abfragen komplexer Daten mit mehreren Hierarchieebenen | Beziehungen, in denen es wenige Eltern und viele Kinder gibt, wie Produkte und Produktbewertungen |
Elasticsearch bietet zwar mehrere Workarounds für SQL-Joins , darunter verschachtelte Abfragen und Eltern-Kind-Beziehungen, aber es ist erwiesen, dass diese Modelle nicht gut skalierbar sind. Beim Entwurf für Anwendungen in großem Maßstab kann es sinnvoll sein, einen alternativen Ansatz mit nativen SQL-Join-Funktionen in Betracht zu ziehen, Rockset .
Rockset ist eine Such- und Analysedatenbank, die für SQL-Suche, Aggregationen und Verknüpfungen beliebiger Daten, einschließlich tief verschachtelter JSON-Daten, entwickelt wurde. Wenn Daten in Rockset gestreamt werden, werden sie in den Kerndatenstrukturen der Datenbank codiert, die zum Speichern und Indizieren der Daten für einen schnellen Abruf verwendet werden. Rockset indiziert die Daten auf eine Weise, die schnelle Abfragen, einschließlich Verknüpfungen, mithilfe seines SQL-basierten Abfrageoptimierers ermöglicht. Daher ist keine Datenmodellierung im Voraus erforderlich, um SQL-Verknüpfungen zu unterstützen.
Eine der Herausforderungen bei Elasticsearch besteht darin, die Beziehung bei Datenaktualisierungen effizient beizubehalten. Einer der Gründe dafür ist, dass Elasticsearch auf Apache Lucene basiert, das Daten in unveränderlichen Segmenten speichert, sodass alle Dokumente neu indexiert werden müssen. Rockset verwendet RocksDB, einen von Meta als Open Source bereitgestellten Schlüssel-Wert-Speicher, der für Datenmutationen entwickelt wurde, um Aktualisierungen auf Feldebene effizient unterstützen zu können, ohne ganze Dokumente neu indexieren zu müssen.
Vergleichen wir den Ansatz der Eltern-Kind-Beziehung in Elasticsearch mit einer SQL-Abfrage in Rockset.
Im obigen Beispiel der Eltern-Kind-Beziehung haben wir Beiträge mit mehreren Kommentaren modelliert, indem wir zwei Dokumenttypen erstellt haben:
Beiträge oder der übergeordnete Dokumenttyp
Kommentare oder die untergeordneten Dokumenttypen
Wir haben eine eindeutige Kennung, die übergeordnete ID, verwendet, um die Beziehung zwischen den übergeordneten und untergeordneten Dokumenten herzustellen. Zum Abfragezeitpunkt verwenden wir die Elasticsearch DSL, um Kommentare für einen bestimmten Beitrag abzurufen.
In Rockset würden die Daten mit den Beiträgen in einer Sammlung gespeichert, einer Tabelle in der relationalen Welt, während die Daten mit den Kommentaren in einer separaten Sammlung gespeichert würden. Zum Abfragezeitpunkt würden wir die Daten mithilfe einer SQL-Abfrage zusammenführen.
Hier sind die beiden Ansätze nebeneinander:
POST /blog/posts/1 { "title": "Elasticsearch Modeling", "content": "A post about data modeling in Elasticsearch" } POST /blog/comments/2?parent=1 { "text": "Great post!" } POST /blog/comments/3?parent=1 { "text": "I learned a lot from this." }
Um einen Beitrag anhand seines Titels und aller seiner Kommentare abzurufen, müssen Sie eine Abfrage wie folgt erstellen.
GET /posts/_search { "query": { "bool": { "must": [ { "match": { "title": "Exploring Elasticsearch Models" } } ] } }, "inner_hits": { "_source": ["text"], "name": "comments", "path": "comments" } }
Um diese Daten anschließend abzufragen, müssen Sie lediglich eine einfache SQL-Abfrage schreiben.
SELECT p.title, p.content, c.text FROM posts p JOIN comments c ON p.post_id = c.post_id WHERE p.post_id = 1;
Wenn Sie mehrere Datensätze haben, die für Ihre Anwendung zusammengeführt werden müssen, ist Rockset einfacher und skalierbarer als Elasticsearch. Es vereinfacht auch den Betrieb, da Sie Ihre Daten nicht neu modellieren, Aktualisierungen verwalten oder Vorgänge neu indizieren müssen.
In diesem Blog finden Sie einen Überblick über die verschachtelten Feldtypen und Abfragen sowie die Eltern-Kind-Beziehungen in Elasticsearch mit dem Ziel, Ihnen bei der Ermittlung des besten Datenmodellierungsansatzes für Ihre Arbeitslast zu helfen.
Die verschachtelten Feldtypen und Abfragen sind für Eins-zu-eins- oder Eins-zu-viele-Beziehungen nützlich, bei denen die Beziehung in einem einzigen Dokument verwaltet wird. Dies gilt als einfacherer und skalierbarerer Ansatz für das Beziehungsmanagement.
Das Eltern-Kind-Beziehungsmodell eignet sich besser für Eins-zu-viele- bis Viele-zu-viele-Beziehungen, bringt jedoch eine höhere Komplexität mit sich, insbesondere da die Beziehungen auf einen bestimmten Shard beschränkt bleiben müssen.
Wenn eine der Hauptanforderungen Ihrer Anwendung die Modellierung von Beziehungen ist, kann es sinnvoll sein, Rockset in Betracht zu ziehen. Rockset vereinfacht die Datenmodellierung und bietet einen skalierbareren Ansatz für das Beziehungsmanagement mithilfe von SQL-Joins. Sie können die Leistung von Elasticsearch und Rockset vergleichen und gegenüberstellen, indem Sie noch heute eine kostenlose Testversion mit 300 $ Guthaben starten .