Vor sechs Monaten habe ich darüber geschrieben , warum wir ClickHouse durch Apache Doris als OLAP-Engine für unser Datenverwaltungssystem ersetzt haben . Damals hatten wir Probleme mit der automatischen Generierung von SQL-Anweisungen. Im Laufe der Tage haben wir so große Fortschritte gemacht, dass wir als Referenz für Sie dienen können, also bin ich wieder hier.
Wir haben Large Language Models (LLM) eingeführt, um unsere Doris-basierten OLAP-Dienste zu stärken.
Unser Anreiz bestand darin, unseren internen Mitarbeitern die steile Lernkurve des SQL-Schreibens zu ersparen. Daher haben wir LLM als Zwischenprodukt verwendet. Es wandelt Fragen in natürlicher Sprache in SQL-Anweisungen um und sendet die SQLs zur Ausführung an die OLAP-Engine.
Wie bei jeder KI-bezogenen Erfahrung stießen wir auf einige Reibungspunkte:
LLM versteht keine Datenjargons wie „Felder“, „Zeilen“, „Spalten“ und „Tabellen“. Stattdessen können sie Geschäftsbegriffe wie „Unternehmenseinkommen“ und „DAU“ perfekt übersetzen, um die es in den Feldern/Zeilen/Spalten im Grunde geht. Das bedeutet, dass es nur dann gut funktionieren kann, wenn die Analysten bei der Eingabe ihrer Fragen genau das richtige Wort verwenden, um auf die benötigte Kennzahl zu verweisen.
Das von uns verwendete LLM ist langsam in der Schlussfolgerung. Die Antwort dauert über 10 Sekunden. Da Gebühren per Token erhoben werden, wird die Kosteneffizienz zum Problem.
Obwohl das LLM auf einer großen Sammlung öffentlicher Datensätze trainiert wird, ist es über Nischenwissen unzureichend informiert. In unserem Fall ist das LLM mit Indie-Songs kaum vertraut. Selbst wenn die Songs in unserer Datenbank enthalten sind, kann das LLM sie daher nicht richtig identifizieren.
Manchmal erfordern unsere Eingabefragen angemessene und aktuelle rechtliche, politische, finanzielle und regulatorische Informationen, die nur schwer in einen Schulungsdatensatz oder eine Wissensdatenbank aufgenommen werden können. Wir müssen das LLM mit breiteren Informationsbasen verbinden, um vielfältigere Aufgaben erfüllen zu können.
Wir beseitigen diese Probleme nach und nach.
Für Problem Nr. 1 führen wir eine semantische Schicht zwischen dem LLM und der OLAP-Engine ein. Diese Schicht übersetzt Geschäftsbegriffe in die entsprechenden Datenfelder. Es kann Datenfilterbedingungen aus den verschiedenen Formulierungen in natürlicher Sprache identifizieren, sie mit den beteiligten Metriken in Beziehung setzen und dann SQL-Anweisungen generieren.
Darüber hinaus kann die semantische Schicht die Berechnungslogik optimieren. Wenn Analysten eine Frage eingeben, die eine komplizierte Abfrage beinhaltet, beispielsweise eine Verknüpfung mehrerer Tabellen, kann die semantische Ebene diese in mehrere Einzeltabellenabfragen aufteilen, um semantische Verzerrungen zu reduzieren.
Um die Kosteneffizienz bei der Verwendung von LLM zu erhöhen, bewerten wir die Berechnungskomplexität aller Szenarien, wie z. B. Metrikberechnung, detailliertes Abrufen von Datensätzen und Benutzersegmentierung. Anschließend erstellen wir Regeln und widmen den LLM-Parsing-Schritt nur komplizierten Aufgaben. Das bedeutet, dass bei einfachen Rechenaufgaben das Parsen übersprungen wird.
Wenn ein Analyst beispielsweise „Sagen Sie mir die Einnahmen der wichtigsten Musikplattformen“ eingibt, erkennt das LLM, dass diese Frage nur mehrere Metriken oder Dimensionen umfasst, sodass es sie nicht weiter analysiert, sondern direkt zur SQL-Generierung und -Ausführung sendet. Dies kann die Antwortzeit auf Abfragen erheblich verkürzen und die API-Kosten senken.
Um das LLM mit Nischenwissen auszustatten, haben wir dem LLM einen Schema Mapper vorgeschaltet. Der Schema Mapper ordnet die Eingabefrage einer externen Wissensdatenbank zu, und dann führt der LLM die Analyse durch.
Wir testen und optimieren den Schema Mapper ständig. Wir kategorisieren und bewerten Inhalte in der externen Wissensdatenbank und führen verschiedene Mapping-Ebenen durch (Volltext-Mapping und Fuzzy-Mapping), um eine bessere semantische Analyse zu ermöglichen.
Wir haben Plugins verwendet, um das LLM mit weiteren Informationsfeldern zu verbinden, und wir haben verschiedene Integrationsmethoden für verschiedene Arten von Plugins:
Einbetten lokaler Dateien : Dies ist besonders nützlich, wenn wir dem LLM die neuesten Regulierungsrichtlinien „beibringen“ müssen, bei denen es sich häufig um Textdateien handelt. Zunächst vektorisiert das System die lokale Textdatei, führt semantische Suchen durch, um passende oder ähnliche Begriffe in der lokalen Datei zu finden, extrahiert die relevanten Inhalte und fügt sie in das LLM-Analysefenster ein, um eine Ausgabe zu generieren.
Plugins von Drittanbietern : Der Marktplatz ist voll von Plugins von Drittanbietern, die für alle möglichen Branchen konzipiert sind. Mit ihnen ist der LLM in der Lage, vielfältige Themen zu bearbeiten. Jedes Plugin verfügt über eigene Eingabeaufforderungen und Aufruffunktionen. Sobald die Eingabefrage auf eine Eingabeaufforderung trifft, wird das entsprechende Plugin aufgerufen.
Nachdem wir mit den oben genannten vier Optimierungen fertig sind, entsteht das SuperSonic-Framework.
Lassen Sie mich Sie nun durch dieses Framework führen:
Ein Analyst gibt eine Frage ein.
Der Schema Mapper ordnet die Frage einer externen Wissensdatenbank zu.
Wenn in der externen Wissensdatenbank übereinstimmende Felder vorhanden sind, wird die Frage vom LLM nicht analysiert. Stattdessen veranlasst eine Metrikberechnungsformel, dass die OLAP-Engine mit der Abfrage beginnt. Wenn kein passendes Feld vorhanden ist, wird die Frage in das LLM eingegeben.
Basierend auf den vordefinierten Regeln bewertet das LLM den Komplexitätsgrad der Frage. Wenn es sich um eine einfache Abfrage handelt, wird sie direkt an die OLAP-Engine weitergeleitet. Wenn es sich um eine komplizierte Abfrage handelt, wird sie semantisch analysiert und in eine DSL-Anweisung umgewandelt.
Auf der semantischen Ebene wird die DSL-Anweisung basierend auf ihrem Abfrageszenario aufgeteilt. Wenn es sich beispielsweise um eine Mehrtabellen-Join-Abfrage handelt, generiert diese Ebene mehrere SQL-Anweisungen für Einzeltabellenabfragen.
Beispiel:
Um zu beantworten, ob ein bestimmtes Lied in Varietés aufgeführt werden kann, ruft das System das OLAP-Data-Warehouse für Details zum Lied ab und präsentiert ihm Ergebnisse aus dem Drittanbieter-Plugin „Commercial Use Query“.
Was den OLAP-Teil dieses Frameworks betrifft, so sieht unsere aktuelle OLAP-Pipeline nach mehreren Runden der Architekturentwicklung so aus.
Rohdaten werden in Tags und Metriken sortiert, die von den Analysten individuell definiert werden. Die Tags und Metriken werden einheitlich verwaltet, um inkonsistente Definitionen zu vermeiden. Anschließend werden sie für verschiedene Abfragen zu verschiedenen Tagsets und Metriksets kombiniert.
Aus unserer Erfahrung in der Architekturoptimierung haben wir zwei wesentliche Erkenntnisse für Sie gezogen.
1. Optimieren Sie die Links
Bevor wir Apache Doris einführten, hatten wir ClickHouse, um die Berechnung von Tags und Metriken zu beschleunigen, und Elasticsearch, um dimensionale Daten zu verarbeiten. Das sind zwei Analyse-Engines und wir müssen die Abfrageanweisungen an beide anpassen. Es war wartungsintensiv.
Daher haben wir ClickHouse durch Apache Doris ersetzt und die Elasticsearch-Katalogfunktion genutzt, um Elasticsearch-Daten mit Doris zu verbinden. Auf diese Weise machen wir Doris zu unserem einheitlichen Abfrage-Gateway.
2. Teilen Sie die flachen Tische
In frühen Versionen unserer OLAP-Architektur haben wir Daten in flachen Tabellen abgelegt, was die Sache schwierig machte. Zum einen absorbierten flache Tabellen die gesamte Schreiblatenz der Upstreams, was zu einem erheblichen Verlust an Datenechtheit führte. Zum anderen handelte es sich bei 50 % der Daten in einer flachen Tabelle um Dimensionsdaten, die selten aktualisiert wurden. Mit jedem neuen flachen Tisch kamen einige umfangreiche Dimensionsdaten, die viel Speicherplatz beanspruchten.
Daher teilen wir die flachen Tabellen in metrische Tabellen und Dimensionstabellen auf. Da sie unterschiedlich schnell aktualisiert werden, fügen wir sie in unterschiedliche Datenmodelle ein.
Metriktabellen : Wir ordnen Metrikdaten im Aggregate Key-Modell von Apache Doris an, was bedeutet, dass neue Daten mit den alten Daten über SUM, MAX, MIN usw. zusammengeführt werden.
Dimensionstabellen : Diese Tabellen liegen im Unique Key-Modell von Apache Doris vor, was bedeutet, dass der neue Datensatz den alten ersetzt. Dies kann die Leistung in unseren Abfrageszenarien erheblich steigern.
Sie fragen sich vielleicht: Verursacht dies Probleme bei Abfragen, da die meisten Abfragen Daten aus beiden Tabellentypen erfordern? Keine Sorge, wir lösen dieses Problem mit der Rollup-Funktion von Doris. Auf der Grundlage der Basistabellen können wir die Dimensionen auswählen, die wir benötigen, um Rollup-Ansichten zu erstellen, die automatisch GROUP BY
ausführen. Dadurch entfällt die Notwendigkeit, Tags für jede Rollup-Ansicht zu definieren, und Abfragen werden erheblich beschleunigt.
Aufgrund unserer Erfahrung mit Apache Doris finden wir auch einige andere Funktionalitäten praktisch, deshalb liste ich sie hier auch für Sie auf:
1. Materialisierte Sicht
Eine materialisierte Ansicht ist ein vorberechneter Datensatz. Dies ist eine Möglichkeit, Abfragen zu beschleunigen, wenn Sie häufig auf Daten bestimmter Dimensionen zugreifen müssen. In diesen Szenarien definieren wir abgeleitete Tags und Metriken basierend auf den Originalen. Beispielsweise erstellen wir eine abgeleitete Metrik, indem wir Metrik 1, Metrik 2 und Metrik 3 kombinieren: sum(m1+m2+m3)
. Dann können wir eine materialisierte Ansicht dafür erstellen. Gemäß dem Veröffentlichungsplan von Doris wird Version 2.1 Materialized Views mit mehreren Tabellen unterstützen, und wir freuen uns darauf.
2. Flink-Doris-Connector
Dies dient der Exactly-Once-Garantie bei der Datenaufnahme. Der Flink-Doris-Connector implementiert einen Checkpoint-Mechanismus und ein zweistufiges Commit und ermöglicht die automatische Datensynchronisierung von relationalen Datenbanken mit Doris.
3. Verdichtung
Wenn die Anzahl der Aggregationsaufgaben oder das Datenvolumen für Flink überwältigend wird, kann es zu enormen Latenzzeiten bei der Datenkomprimierung kommen. Wir lösen das mit Vertical Compaction und Segment Compaction. Die vertikale Komprimierung unterstützt das Laden nur eines Teils der Säulen und kann so den Speicherverbrauch beim Komprimieren flacher Tische reduzieren. Durch die Segmentkomprimierung kann vermieden werden, dass während des Datenschreibens zu viele Segmente generiert werden, und ermöglicht die Komprimierung beim gleichzeitigen Schreiben.
Mit dem Ziel, die Kosten zu senken und die Serviceverfügbarkeit zu erhöhen, planen wir, die neu veröffentlichte Storage-Compute-Trennung und Cross-Cluster-Replikation von Doris zu testen und nehmen alle Ideen und Eingaben zum SuperSonic-Framework und zum Apache-Doris-Projekt auf.