Warum wir Loon entwickelt haben: eine Speicher-Engine für KI-Daten, die sich ständig verändert.

  • Engineering
June 05, 2026
Ted Xu

Dieser Blog wurde ursprünglich auf zilliz.com veröffentlicht und wurde mit Genehmigung wiederveröffentlicht.

Wichtigste Erkenntnisse

Dies ist ein langer, tiefgehender technischer Tauchgang, daher hier die wichtigsten Punkte, bevor wir ins Detail gehen.

  • KI-Datensätze sind keine statischen Tabellen. Dieselben Zeilen ändern sich ständig, wenn Teams Einbettungsmodelle ersetzen, spärliche Vektoren hinzufügen, Beschriftungen überarbeiten, Beschriftungen wieder auffüllen, Indizes neu erstellen und Offline-Analysen durchführen.
  • Herkömmliche Speicherlayouts versagen in dreierlei Hinsicht: Lange Vektorspalten machen Backfills teuer, ein einziges Dateiformat kann sowohl Scans als auch Punktlesungen nicht gut bedienen, und die Speicherung in privaten Datenbanken zwingt externe Pipelines dazu, zusätzliche Kopien der Wahrheit zu erstellen.
  • Loon ist die neue Speicher-Engine für Milvus und Zilliz Vector Lakebase. Sie basiert auf hybriden Dateiformaten, Zeilen-ID-Abgleich und einem Manifest, das den Versionsstand des Datensatzes definiert.
  • Ziel ist es, dass ein einziger Vektordatensatz Online-Suche, Offline-Analyse, Backfills, Verdichtung und externe Berechnungen unterstützt, ohne dass Daten ständig kopiert, neu geschrieben oder neu importiert werden müssen.

Einführung

Eine Zeit lang gab es ein Argument gegen Vektordatenbanken, das vernünftig klang.

Traditionelle Datenbanken speichern bereits Integer, Strings, JSON, Blobs und Indizes. Warum nicht einen Typ _vector_ hinzufügen , daneben einen ANN-Index erstellen und das Ganze abhaken?

Für die frühe semantische Suche funktioniert das gut genug. Eine Vektorspalte plus ein Index können eine Demo, eine kleine RAG-Anwendung oder eine interne Suchfunktion unterstützen. Das Problem zeigt sich später, wenn der Datensatz sich weniger wie eine Tabelle und mehr wie ein KI-Datensystem verhält.

Ein Produktionsvektordatensatz hat Zeilen, Primärschlüssel, skalare Felder und abfragbare Spalten. In diesem Sinne sieht er wie eine Datenbanktabelle aus. Aber er hat auch den Umfang und die Workflow-Form eines Datensees. Er kann Hunderte von Millionen von Datensätzen enthalten. Sie wird wiederholt von Spark, Ray, DuckDB, Schulungspipelines, Auswertungsaufträgen und Datenqualitätssystemen gelesen und neu geschrieben.

Er hängt auch von der Objektspeicherung ab. Die Quellobjekte sind häufig Videos, Bilder, PDFs, Audiodateien oder Webdokumente, die in S3, GCS, OSS oder einem anderen Objektspeicher verbleiben. Die Datenbank speichert Verweise, Metadaten, abgeleitete Merkmale und Indizes. Dann kommen Dinge hinzu, für die herkömmliche Speichermodelle nicht als erstklassige Objekte konzipiert wurden: dichte Einbettungen, spärliche Vektoren, Beschriftungen, Vektorindizes, Textindizes, Löschprotokolle, Statistiken, Modellversionen, Parserversionen, externe Blob-Referenzen und die Versionsbeziehungen zwischen all diesen Objekten.

Das ist der Punkt, an dem "einfach eine Vektorspalte hinzufügen" zu scheitern beginnt. Das Problem ist nicht, ob eine Datenbank Vektorbytes speichern kann. Viele Systeme können das. Die schwierigere Frage ist , ob das Speichermodell damit umgehen kann, wie sich Vektordaten ändern, wie sie abgefragt werden und wie sie über den KI-Datenstapel verteilt werden.

Aus diesem Grund haben wir Loon entwickelt, die neue Speicher-Engine für Milvus und Zilliz Vector Lakebase (die nächste Evolution der Zilliz Cloud).

Loon wurde mit drei Ideen entwickelt:

  1. Verwenden Sie verschiedene physische Formate für verschiedene Arten von Spalten.
  2. Ausrichten dieser Spalten durch einen gemeinsamen Zeilen-ID-Raum.
  3. Verwendung eines Manifests, um den Versionsstatus des Datensatzes zu definieren.

Um zu sehen, warum diese Teile wichtig sind, beginnen wir mit einem gängigen multimodalen Workflow.

Ein Vektordatensatz ist nie wirklich fertig.

Stellen Sie sich vor, ein KI-Team erstellt einen Videodatensatz für multimodales Training.

Ein langes Video wird in den Objektspeicher hochgeladen. Eine Pipeline schneidet es auf der Grundlage von Szenenwechseln, Aufnahmegrenzen oder Zeitfenstern in Clips. Clips, die zu lang oder zu kurz, verschwommen, doppelt vorhanden oder von schlechter Qualität sind, werden herausgefiltert. Die verbleibenden Clips werden von einem ästhetischen Modell bewertet, von einem anderen Modell mit Untertiteln versehen, von einem Bildsprachmodell eingebettet und in einer Vektordatenbank zur Suche, Deduplizierung und Filterung von Trainingsdaten gespeichert.

Auf den ersten Blick sieht der Arbeitsablauf einfach aus:

video
→ clips
→ metadata
→ aesthetic_score
→ caption
→ embedding
→ search / dedup / training data filtering

Aber der Datensatz ist nicht vollständig ausgebildet.

  • In der ersten Woche enthält die Tabelle vielleicht nur clip_id, video_id, start_offset und duration.
  • In der zweiten Woche fügt das Team aesthetic_score hinzu.
  • In der dritten Woche wird ein Untertitelungsmodell ausgeführt, und jeder Clip erhält eine caption.
  • In der vierten Woche geht das erste Einbettungsmodell online, und jeder Clip erhält eine 768-dimensionale CLIP-Einbettung.
  • Einen Monat später wechselt das Team das Modell und füllt embedding_v2 wieder auf, jetzt mit 1024 Dimensionen.
  • Zwei Monate später wird die hybride Suche zu einer Anforderung, so dass das Team eine spärliche Vektorsäule hinzufügt.
  • Drei Monate später werden die Beschriftungen von Menschen überprüft und müssen an Ort und Stelle korrigiert werden.

Der Datensatz wurde nie fertiggestellt. Es wurden immer wieder neue Interpretationen der gleichen zugrunde liegenden Zeilen angehäuft.

Dies ist einer der Hauptunterschiede zwischen Vektordaten und herkömmlichen Geschäftsdaten. Dieselbe Zeile wird immer wieder neu verarbeitet. Und durch die Skalierung wird dies von einer Unannehmlichkeit zu einem Speicherproblem: Multimodale Datensätze bestehen oft nicht aus Millionen von Datensätzen, sondern aus Hunderten von Millionen oder Milliarden. LAION-5B ist eine nützliche Referenz für diese Form - Milliarden von Bild-Text-Paaren, jedes mit Metadaten, Beschriftungen und Einbettungen. Der schwierige Teil ist also nicht das erste Einfügen. Der schwierige Teil ist alles, was passiert, nachdem der Datensatz anfängt, sich zu entwickeln. Diese Entwicklung wirft drei Probleme auf.

Das erste Problem: Lange Spalten machen die Schreibvergrößerung teuer

Spaltenbasierte Formate wie Parquet eignen sich hervorragend für viele analytische Arbeitslasten. Sie funktionieren gut, wenn die Schemata ziemlich stabil sind, die Daten häufiger gelesen als neu geschrieben werden, die Scans nur eine Teilmenge der Spalten betreffen und die Komprimierung wichtig ist. Das ist die Welt, für die viele analytische Formate optimiert wurden.

Vektorielle Zeilen sind viel breiter als analytische Zeilen

TPC-H lineitem ist eine gute Ausgangsbasis. Sie hat 16 Spalten: Ganzzahlige Schlüssel, Dezimalwerte, Datumsangaben, kurze Zeichenfolgen und ein kleines Kommentarfeld. Eine unkomprimierte Zeile ist etwa 150 Byte groß. Nach der Komprimierung kann sie noch viel kleiner sein. Mit einer 64 MB großen Zeilengruppe kann ein Speichersystem Hunderttausende von Zeilen in eine Gruppe packen.

Vektordatensätze sehen nicht so aus.

Ein Bild-Text-Datensatz im LAION-Stil kommt dem, was viele KI-Pipelines heute produzieren, sehr viel näher. Jede Zeile hat immer noch gewöhnliche Metadaten: eine URL, eine Beschriftung, Breite, Höhe, Qualitätsbewertungen, Beschriftungen usw. Sobald jedoch die Einbettung hinzugefügt wird, ändert sich die physische Form der Zeile.

Ein 768-dimensionaler CLIP-Vektor benötigt etwa 1,5 KB in fp16 oder 3 KB in fp32. Diese eine Spalte kann viel größer sein als eine ganze TPC-H lineitem Zeile.

Und 768 Dimensionen sind nach heutigen Maßstäben nicht ungewöhnlich oder groß. Eine 1024- oder 2048-dimensionale Einbettung ist in multimodalen Pipelines üblich. OpenAIs text-embedding-3-large geht bis zu 3072 Dimensionen, was etwa 12 KB pro Vektor in fp32 entspricht.

Der Vergleich ist deutlich:

Form des DatensatzesUngefähre ZeilengrößeWas dominiert die Zeile
TPC-H-Zeilensatz~150 Bytes unkomprimiertSkalare und kurze String-Felder
LAION-artige Zeile mit 768-dim fp16-Vektor~1,5 KB+Einbettung
LAION-ähnliche Zeile mit 768-dim fp32-Vektor~3 KB+Einbettung
Zeile mit 3072-dim fp32-Vektor~12 KB+ allein für den VektorEinbettung

In vielen KI-Datensätzen ist die Vektorspalte nicht nur ein weiteres Feld. Physikalisch gesehen ist sie der größte Teil der Zeile. Das verändert die Kosten der Schemaentwicklung.

Das Hinzufügen einer Vektorspalte kann Hunderte von Gigabyte bedeuten

Angenommen, ein Datensatz enthält 100 Millionen Videoclips. Das Hinzufügen einer neuen 1024-dimensionalen fp32-Einbettungsspalte bedeutet das Schreiben von etwa 400 GB an rohen Vektordaten. Dabei sind Statistiken, Indizes, Metadatenaktualisierungen, Objektspeicher-Overhead, Validierung oder Serving-Path-Integration noch nicht berücksichtigt.

Wenn das Team jeden Monat eine oder zwei vektorähnliche Spalten hinzufügt, z. B. embedding_v2, sparse_vector oder Rerank-Funktionen, wird die Schemaentwicklung zu einer wiederkehrenden daAta-Engineering-Aufgabe, die sich auf Hunderte von Gigabyte oder Terabyte beläuft.

Kleine logische Updates können große physische Rewrites auslösen

Aktualisierungen sind ebenso wichtig.

In spaltenorientierten Systemen werden alte Daten normalerweise nicht an Ort und Stelle aktualisiert. Ein Löschprotokoll zeichnet auf, was sich geändert hat, und die Verdichtung schreibt später die aktiven Zeilen in neue Dateien. Dieses Modell ist überschaubar, wenn die Zeilen klein sind.

Bei Vektordaten kann eine kleine logische Aktualisierung eine große physische Neuschreibung auslösen.

Ein menschlicher Überprüfungsauftrag korrigiert vielleicht nur ein paar hundert Bytes in einer Beschriftung. Wenn aber die Beschriftung, der dichte Vektor, der spärliche Vektor und andere abgeleitete Merkmale denselben physischen Dateilebenszyklus haben, kann das System am Ende auch die Vektoren neu schreiben. Die logische Änderung ist gering. Die physische E/A kann riesig sein.

Dies ist das Problem der Schreibverstärkung bei der Vektorspeicherung. Der teure Teil ist nicht nur, dass Vektoren groß sind. Es liegt daran, dass große abgeleitete Felder und kleine veränderbare Felder oft durch ein Speicherlayout, das sie als eine Einheit behandelt, miteinander verbunden werden.

Bei KI-Datensätzen ist das Backfill eine Routineaufgabe

Bei herkömmlichen analytischen Tabellen kann eine Schemaentwicklung nur gelegentlich auftreten. Bei KI-Datensätzen ist sie Routine. Erfassungsmodelle werden aktualisiert. Einbettungsmodelle werden ersetzt. Spärliche Vektoren werden später hinzugefügt. Rerank-Merkmale erscheinen. Menschliche Beschriftungen werden korrigiert. Governance-Tags werden wieder aufgefüllt. Indizes werden neu aufgebaut.

Diese Vorgänge sind keine einfachen Anhänge. Sie ändern oder erweitern häufig bestehende Zeilen.

Aus diesem Grund kann die Vektorspeicherung nicht nur auf den Scandurchsatz optimiert werden. Sie muss auch Backfills und partielle Aktualisierungen billiger machen.

Das zweite Problem: Dieselben Daten müssen Scans und Punktlesungen unterstützen

Nachdem die Daten geschrieben wurden, teilt sich der Lesepfad auf. Ein und derselbe Vektordatensatz hat in der Regel zwei unterschiedliche Zugriffsmuster: analytisches Scannen und punktuelles Lesen.

Analytische Workloads benötigen breite, komprimierte Scans

Eine Pipeline kann Filter wie z. B.:

WHERE aesthetic_score > 0.8 AND duration > 5

Oder sie kann Offline-Analysen, vollständige Einbettungsbewertungen, BM25-Statistiken, Bitmap-Konstruktionen, Datenqualitätsprüfungen, Zählungen und Gruppierungen durchführen.

Dieses Muster liest viele Zeilen, aber nur wenige Spalten. Es bevorzugt sequenzielle E/A, größere Zeilengruppen, Komprimierung, Spaltenbeschneidung, Batch-Dekodierung und vektorisierte Ausführung.

Große Zeilengruppen sind hier hilfreich. Sie ermöglichen es, mit einer einzigen E/A-Anforderung eine große Menge an nützlichen Daten abzurufen, die Komprimierungseffizienz zu verbessern und der Ausführungsmaschine genügend zusammenhängende Daten zur Verfügung zu stellen, um den Overhead zu amortisieren. Wenn mehrere Spalten zusammen gelesen werden, trägt die Organisation dieser Spalten für den Scan-Durchsatz auch dazu bei, die Cache-Misses während der vektorisierten Ausführung zu reduzieren.

Parquet ist auf diesem Weg stark.

ANN-Ergebnisse benötigen enge Suchabfragen auf Zeilenebene

Nachdem die ANN-Suche die IDs der Kandidatenzeilen zurückgegeben hat, muss das System häufig Felder wie abrufen:

caption
embedding
rerank feature
video_uri
metadata

Dieses Muster liest weniger Zeilen, oft Hunderte oder Tausende, aber es benötigt einen genauen Zugriff nach Zeilen-ID. Es möchte eine bestimmte Zeile und Spalte finden, nur den erforderlichen Bytebereich abrufen und vermeiden, dass eine ganze Zeilengruppe abgerufen wird, nur um ein paar Datensätze zu erhalten.

Point Lookup hat fast die gegenteilige Vorliebe für das Scannen. Sie will eine kleinere Lesegranularität. Im Idealfall kann die Speicherschicht das relevante Segment oder den Bytebereich anhand der Zeilen-ID finden, nur diesen Bereich lesen und nur die für das Ergebnis benötigten Daten dekodieren.

Auch bei der Komprimierung gibt es einen anderen Kompromiss. Bei Scans lohnt sich eine stärkere Komprimierung oft, weil das System viele Daten liest und E/A einspart. Bei der Punktsuche kann die Komprimierung zu einer Belastung werden, wenn das Abrufen einer Zeile die Dekodierung eines viel größeren komprimierten Blocks erfordert.

Ein Layout kann nicht für beide Pfade optimiert werden

Dies ist der Kernkonflikt. Skalare Filterung und Analysen erfordern breite, komprimierte, scanfreundliche Layouts. Die Vektorsuche benötigt enge, präzise, zeilenadressierbare Layouts.

Ein einziges Dateiformat kann beide bis zu einem gewissen Grad unterstützen, aber es kann nicht für beide gleichzeitig optimal sein.

Wenn sich alle Spalten in Parquet befinden, sind skalare Scans bequem. Aber die ANN-Suche nach dem Abruf wird schwieriger. Das System benötigt vielleicht nur ein paar hundert Vektoren, Beschriftungen oder Metadatensätze, während die Speicherebene möglicherweise große Zeilengruppen lesen muss, die größtenteils irrelevante Zeilen enthalten.

Auf einer lokalen SSD können Cache und mmap einen Teil dieser Kosten verbergen. Sobald die Daten im Objektspeicher gespeichert sind, werden die Kosten deutlicher sichtbar. Jeder Cache-Miss kann zu einem Remote Range Read werden. Wenn Kandidatenzeilen über viele Zeilengruppen verstreut sind, kann eine einzige Abfrage mehrere Lesevorgänge auslösen, die jeweils mehr Daten abrufen, als die Abfrage benötigt. In einem schlecht angelegten Layout kann das Abrufen von 1.000 Kandidatenzeilen leicht zu Dutzenden oder Hunderten von Megabyte unnötiger E/A führen, in Extremfällen sogar zu viel mehr.

Die Verkleinerung von Zeilengruppen hilft bei der Punktsuche, schadet aber den Scans. Zu viele kleine Fragmente verringern die Komprimierungseffizienz, erhöhen den Metadaten-Overhead und stören die langen sequenziellen Lesevorgänge, auf die Analyseprogramme angewiesen sind.

Das Problem besteht also nicht darin, eine einzige magische Zeilengruppengröße zu finden. Das Problem ist, dass ein und derselbe Datensatz sich wie zwei verschiedene Speichersysteme verhalten soll.

Die hybride Suche zwingt beide Wege in eine Abfrage

Bei der hybriden Suche ist der Konflikt noch schwerer zu ignorieren. Eine einzelne Abfrage kann zunächst skalare Filter anwenden:

aesthetic_score > 0.8 AND duration > 5

Dann führt sie die ANN-Suche durch.

Dann werden Überschrift, Vektor und Metadaten nach Zeilen-ID abgerufen.

Für den Benutzer ist dies eine einzige Suchanfrage. Für die Speicherebene ist es sowohl ein analytischer Scan als auch eine zufällige Suche mit niedriger Latenz.

Aus diesem Grund braucht die Vektorspeicherung mehr als nur eine bessere Parquet-Einstellung. Es muss eine Möglichkeit geben, verschiedene Spalten so zu platzieren, wie sie tatsächlich gelesen werden.

Das dritte Problem: Der Datensatz befindet sich nicht in einer einzigen Engine

Die ersten beiden Probleme treten innerhalb der Datenbank auf. Das dritte Problem tritt an der Grenze zwischen den Systemen auf.

KI-Datenpipelines umfassen viele Systeme

Im Video-Workflow passiert nur sehr wenig innerhalb der Vektordatenbank selbst.

Die Rohvideos befinden sich im Objektspeicher. Die Clip-Generierung kann in Spark oder Ray ausgeführt werden. Die ästhetische Bewertung kann in einem GPU-Dienst ausgeführt werden. Die Untertitelung kann in einer LLM-Inferenz-Pipeline ausgeführt werden. Einbettungen können von einem anderen GPU-Job generiert werden. Spärliche Vektoren können von einem SPLADE-Dienst stammen. Offline-Evaluierung, Filterung von Trainingsdaten, menschliche Überprüfung und Verwaltungsaufgaben können an anderer Stelle ausgeführt werden.

Die Vektordatenbank dient der Online-Suche, aber der Datensatz wird von vielen Systemen erstellt, korrigiert, ausgewertet und erweitert.

Private Speicherformate erzeugen mehrere Kopien der Wahrheit

Wenn die Datenbank ein privates physisches Format verwendet, das nur sie lesen und schreiben kann, benötigt jeder externe Auftrag einen Export, eine Konvertierung, eine Kopie und einen Import. Dieselbe Sammlung kann in der Datenbank, in einem temporären Spark-Verzeichnis, in einer Auswertungsausgabe und in einem lokalen Backfill-Verzeichnis vorhanden sein. Dann stellt sich die eigentliche Frage:

  • Welche Kopie ist die Quelle der Wahrheit?
  • Welche Kopie enthält das Erfassungsmodell vom letzten Monat?
  • Welche Zeilen wurden bereits durch eine menschliche Überprüfung korrigiert?
  • Welche Spalte des spärlichen Vektors wurde von welchem Modell erzeugt?
  • Welcher Vektorindex ist nach dem Backfill noch gültig?
  • Auf welches ursprüngliche Videoobjekt bezieht sich diese Zeile?

In kleinem Maßstab können Teams manchmal mit Namenskonventionen und manuellen Überprüfungen auskommen. Bei Hunderten von Millionen von Zeilen und Terabytes von Einbettungen wird dies zu einem Konsistenzproblem.

Vektordatensätze brauchen einen gemeinsamen versionierten Zustand

Lakehouse-Systeme haben eine Version dieses Problems für strukturierte Daten aufgegriffen. Bei Iceberg, Delta Lake und Hudi geht es nicht nur um die Speicherung von Dateien. Ihr wichtigster Beitrag besteht darin, dass sich mehrere Engines um denselben Tabellenstatus herum koordinieren können.

Vektordatenbanken benötigen nun eine ähnliche Fähigkeit, aber der Zustand ist komplexer. Er muss nicht nur Tabellendateien und Partitionen, sondern auch Vektorindizes, Textindizes, Sparse Features, Löschprotokolle, Statistiken, Zeilen-ID-Bereiche und Verweise auf externe Blobs umfassen.

Die Frage lautet nicht einfach: "Kann Spark Milvus-Dateien lesen?"

Die Frage ist, nachdem Spark eine Sparse-Vektor-Spalte gefüllt hat, wie weiß Milvus, zu welcher Version diese Spalte gehört, welche Zeilen sie abdeckt, welches Modell sie erzeugt hat und wann Online-Abfragen sie sicher verwenden können?

Die Antwort muss im Speichermodell liegen.

Warum Patches nicht genug sind

Es ist verlockend, dies als drei separate technische Probleme zu betrachten.

  • Schreibverstärkung? Batching hinzufügen.
  • Punktuelle Lesevorgänge? Fügen Sie einen Cache hinzu.
  • Externe Systeme? Fügen Sie Export- und Importwerkzeuge hinzu.

Diese Korrekturen können helfen, aber sie lösen nicht das eigentliche Problem: Ein Vektordatensatz ist physikalisch heterogen.

In dem Videobeispiel sind clip_id, video_id, duration und aesthetic_score kurze skalare Felder. Sie sind nützlich für Filterung und Analyse.

  • caption ist Text. Er kann für BM25, Überprüfung, Korrektur und Backfill verwendet werden.
  • embedding ist ein langer, dichter Vektor. Er wird für den ANN-Abruf und später für das Nachschlagen auf Zeilenebene oder das Reranking verwendet.
  • embedding_v2 ist eine neue Modellausgabe, die oft lange nach dem Einfügen der ursprünglichen Daten aufgefüllt wird.
  • sparse_vector unterstützt die hybride Suche und hat sein eigenes Zugriffsmuster.
  • Das Rohvideo sollte im Objektspeicher verbleiben. Die Datenbank sollte eine Referenz, eine Prüfsumme, einen MIME-Typ, eine Parser-Version und eine Beziehung auf Zeilenebene speichern.
  • Vektorindizes, Textindizes, Statistiken und Löschprotokolle sind abgeleitete Objekte mit einer eigenen Versionssemantik.

Diese Objekte teilen sich eine logische Zeile, aber sie sollten nicht alle das gleiche physische Layout oder den gleichen Lebenszyklus haben.

  • Wenn sie in ein gewöhnliches Tabellenlayout gezwungen werden, werden Aktualisierungen teuer.
  • Wenn sie in ein spaltenförmiges Dateiformat gezwungen werden, wird das Lesen von Punkten teuer.
  • Werden sie als unverbundene Objektdateien behandelt, wird die Versionsverwaltung anfällig.

Das Speichermodell muss also von der Tatsache ausgehen, dass der Datenbestand heterogen ist.

Daraus ergeben sich drei Designanforderungen:

  • Erstens sollten verschiedene Spaltengruppen in unterschiedlichen physischen Formaten gespeichert werden.
  • Zweitens benötigen diese Spaltengruppen einen gemeinsamen Zeilen-ID-Raum, damit sie sich weiterhin wie eine einzige logische Tabelle verhalten können.
  • Drittens benötigt das Dataset ein versioniertes Manifest, das angibt, welche Dateien, Indizes, Protokolle, Statistiken und Objektreferenzen zur aktuellen Ansicht gehören.

Dies ist das Design hinter Loon, unserer neuen Speicher-Engine hinter Milvus und Zilliz Cloud.

Loon: eine Speicher-Engine hinter Milvus und Zilliz Cloud für sich entwickelnde Vektordatensätze

Um all die oben genannten Probleme zu lösen, haben wir Loon entwickelt, die neue Speicher-Engine für Milvus und Zilliz Vector Lakebase (die nächste Evolution von Zilliz Cloud), die für sich entwickelnde Vektordatensätze entwickelt wurde.

Der Name folgt der Tradition der Vogelnamen von Zilliz. Ein Seetaucher ist ein Tauchvogel, der auf Seen lebt, was gut zum Ziel des Systems passt: eine Vektordatenbank sollte nicht jedes Mal einen ganzen Datensee verschieben, scannen oder neu schreiben müssen, wenn sie eine Abfrage durchführt, eine Spalte zurückfüllt oder einen Index erstellt. Sie sollte zunächst die aktuelle Version des Datensatzes verstehen, einschließlich seiner Spalten, Indizes, Statistiken, Löschprotokolle und Objektreferenzen, und dann nur den Teil lesen, den sie tatsächlich benötigt.

Hybride Dateiformate, die Ausrichtung von Zeilen-IDs und das Manifest sind keine drei separaten Funktionen. Sie beruhen auf der gleichen Design-Annahme: Ein Vektordatensatz ist von Natur aus heterogen.

Drei Teile, ein Speichermodell

Hybride Dateiformate tragen der Tatsache Rechnung, dass verschiedene Spalten unterschiedliche Zugriffsmuster haben. Skalare Felder eignen sich gut für Scans und Filter. Vektorfelder benötigen effiziente Nachschlagemöglichkeiten auf Zeilenebene. Rohe Objekte wie Videos, PDFs, Bilder und Audiodateien gehören in den Objektspeicher und nicht in die Datenbankdateien.

Die Ausrichtung von Zeilen-IDs berücksichtigt, dass diese Spalten zwar physisch getrennt sein können, aber dennoch dieselben logischen Zeilen beschreiben. Eine Beschriftung, eine Einbettung, ein Sparse-Vektor und ein Video-URI können sich in unterschiedlichen Dateien und Formaten befinden, müssen aber dennoch zu einem einzigen Ergebnis zusammengeführt werden.

Das Manifest erkennt an, dass der Datensatz nicht einmal geschrieben und dann allein gelassen wird. Er wird von mehreren Systemen, in mehreren Versionen und für mehrere Aufgaben geändert. Indizes, Statistiken, Löschprotokolle, externe Objektreferenzen und Spaltengruppen müssen alle in der gleichen versionierten Ansicht erscheinen.

Aus diesem Grund ist Loon nicht nur ein schnelleres Vektordateiformat. Ein schnelleres Format hilft bei der Punktsuche, aber es löst nicht die Schema-Evolution oder die Multi-Engine-Koordination. Durch die Ausrichtung der Zeilen-IDs verhalten sich geteilte Spalten wie eine einzige Tabelle, aber es wird nicht angegeben, welche Dateien zur aktuellen Version gehören. Ein Manifest kann den Zustand eines Datensatzes beschreiben, aber ohne Spaltengruppen und Zeilen-ID-Abgleich kann es verschiedene physische Layouts innerhalb einer logischen Sammlung nicht sauber darstellen.

Das Speichermodell braucht alle drei: verschiedene Formate für verschiedene Spaltengruppen, einen gemeinsamen Zeilen-ID-Raum, um Zeilen zu rekonstruieren, und ein versioniertes Manifest, das jedem Leser und Schreiber mitteilt, was der Datensatz gerade ist.

Wo Loon in Milvus und Zilliz Vector Lakebase passt

In Milvus wird die alte Segment-Binlog-Speicherschicht durch ein Modell ersetzt, das auf Manifest, ColumnGroup, Dateiformat und Dateisystem-Abstraktionen aufbaut. In Zilliz Vector Lakebase (die nächste Evolution von Zilliz Cloud) gilt die gleiche Richtung für die Vector Lakebase-Architektur: die Vektordatenbank soll schnell sein, während die zugrundeliegenden Daten einfacher zu entwickeln, zu analysieren und mit externen Systemen zu koordinieren sind.

Die Milvus-Komponenten der oberen Ebene behalten ihre vertrauten Rollen. Proxy übernimmt das Routing. QueryCoord und DataCoord übernehmen die Zeitplanung. IndexNode baut Indizes auf. Die anwendungsnahen APIs für Sammlungen, Einfügungen, Suchen und hybride Suchen müssen keine Manifestdateien oder ColumnGroups bereitstellen.

Die Änderung liegt darunter.

DataNode, QueryNode, Segcore, Compaction und externe Konnektoren können über dieselbe Speicherabstraktion arbeiten. Das ist wichtig, weil der Datensatz nicht mehr nur von der Datenbank geschrieben und gelesen wird. Er kann von externen Computersystemen erweitert und gleichzeitig von der Online-Suche genutzt werden.

Auf einer hohen Ebene sehen die Schichten wie folgt aus:

Manifest
→ ColumnGroup
→ file format layer
→ filesystem abstraction

Das Manifest beschreibt den versionierten Zustand des Datensatzes. ColumnGroups bilden eine logische Sammlung in physische Gruppen von Spalten ab. Die Dateiformatebene ermöglicht jeder ColumnGroup die Auswahl eines geeigneten Formats. Die Abstraktion des Dateisystems funktioniert sowohl im Objektspeicher als auch im lokalen Speicher.

Wichtig ist, dass hybride Dateiformate, die Ausrichtung von Zeilen-IDs und das Manifest keine separaten Funktionen sind. Zusammen definieren sie das Speichermodell.

Mit diesem Modell können wir die drei Design-Entscheidungen einzeln betrachten: wie Loon verschiedene ColumnGroups speichert, wie es sie wieder zu Zeilen ausrichtet und wie das Manifest diese Dateien in einen versionierten Datensatz verwandelt.

Design 1: Verwenden Sie das richtige Dateiformat für die richtige Spaltengruppe

Verschiedene Spalten haben unterschiedliche Zugriffsmuster. Sie sollten nicht in dasselbe Dateiformat gezwungen werden.

Loon trennt eine logische Sammlung in ColumnGroups.

  • Skalare Felder, Filterfelder, Geschäftsschlüssel und statistische Felder werden oft gescannt, gefiltert, aggregiert oder für die Abfrageplanung verwendet. Sie profitieren von Komprimierung, Spaltenbeschneidung und Ökosystemkompatibilität. Parquet ist für diese Spalten gut geeignet.
  • Dichte Vektoren, spärliche Vektoren und Rerank-Merkmale werden oft nach dem ANN-Abruf nach Zeilen-ID gelesen. Sie benötigen einen zufälligen Zugriff mit niedriger Latenz, präzise Lesevorgänge im Byte-Bereich und eine selektive Dekodierung. Ein segmentorientiertes Layout ist hier besser geeignet. Loon verwendet Vortex in dieser Richtung.
  • Rohe Objekte wie Videos, PDFs, Bilder und Audiodateien sollten nicht in die Datendateien der Vektordatenbank eingebettet werden. Sie sollten im Objektspeicher verbleiben. Die Datenbank zeichnet Referenzen, Prüfsummen, MIME-Typen, Parser-Versionen und Beziehungen auf Zeilenebene auf.

Für das Videobeispiel könnte ein physisches Layout wie folgt aussehen:

Parquet ColumnGroup:
clip_id / video_id / start_offset / duration / aesthetic_score / caption

Vortex ColumnGroups: embedding embedding_v2 sparse_vector

Object storage: raw video objects

Für die Anwendung ist dies immer noch eine einzige Sammlung. Für die Speicherebene verwenden die verschiedenen Teile dieser Sammlung unterschiedliche physische Formate. Dadurch werden unnötige Neuschreibungen direkt reduziert. Das Hinzufügen von embedding_v2 kann zu einer neuen Vektor ColumnGroup plus einem Manifest Commit werden. Es ist nicht erforderlich, die Beschriftungsspalte, die skalaren Metadaten oder die vorhandene Einbettungsspalte neu zu schreiben.

Die gleiche Idee gilt für spärliche Vektoren, Rerank-Merkmale oder andere abgeleitete Felder. Wenn eine neue Spalte physisch unabhängig und an der Zeilen-ID ausgerichtet werden kann, muss sie nicht unverbundene Spalten durch denselben Rewrite-Pfad ziehen.

Loon passt sich auch an die Verwendung von Dateiformaten an.

Für Parquet sind die Standardeinstellungen nicht immer ideal für vektorlastige Daten. Eine 64-MB-Zeilengruppe kann für die Punktsuche zu groß sein, da ein kleiner zufälliger Lesezugriff viel mehr Daten als nötig abrufen kann. Loon verkleinert Zeilengruppen in relevanten Pfaden auf 1 MB und deaktiviert Kodierungen, wie z. B. die Wörterbuchkodierung von Vektorspalten, wenn sie für zufällig aussehende Vektordaten nicht hilfreich sind.

Für Vortex ist das Layout die wichtigere Arbeit. Loon verwendet ein Layout, das ein Gleichgewicht zwischen Scan-Effizienz und Punktsuche herstellt. Innerhalb einer Zeilengruppe können Segmente aus verwandten Spalten nahe beieinander platziert werden, um das Scannen zu unterstützen. Um Operationen durchzuführen, kann das System durch das Lesen von Teilsegmenten nur die relevanten Bytes abrufen, anstatt ein ganzes Segment zu ziehen.

Loon unterstützt auch die schreibgeschützte Lance-Integration, so dass bestehende Lance-Datensätze als ColumnGroups gemountet werden können, wenn Kompatibilität erforderlich ist.

Was der Benchmark zeigt

In einem lokalen Test, bei dem eine einzelne Datei mit 40.000 Zeilen und dem Schema {id: int64, name: utf8, value: float64, vector: list<float32>[128]} verwendet wurde, zeigte Vortex diese Ergebnisse gegenüber Parquet mit 1 MB Zeilengruppen:

VorgangVortexParquetUnterschied
Nehmen, K=1000 zufällige Zeilen5,8 ms144 ms25x schneller
Vollständiger Vektor-Spalten-Scan21 ms142 ms6,76x schneller
Dateigröße, ~21 MB Rohdaten6,62 MB7,16 MB7% kleiner

Das Ergebnis von take ergibt sich aus der Verringerung der Menge an irrelevanten Daten, die gelesen und dekodiert werden müssen. Das Scan-Ergebnis ergibt sich aus der Komprimierung und der Wahl der Implementierung.

Diese Zahlen sollten mit ihrer Einrichtung verbunden bleiben: 8 vCPU Ubuntu 22.04 KVM, lokales Dateisystem, eine Datei, 40.000 Zeilen, 1 MB Zeilengruppen und das obige Schema. Bei Objektspeicher kann die Netzwerk-E/A dominieren, so dass die Reduzierung der Leseverstärkung noch wichtiger sein kann. Die tatsächlichen Ergebnisse hängen von der Form des Datensatzes, dem Verhalten des Objektspeichers, dem Cache-Status und dem Abfragemuster ab.

Im Großen und Ganzen geht es nicht darum, dass jede Spalte Vortex verwenden sollte.

Es geht darum, dass Vektordatensätze eine Wahl des Dateiformats auf der Ebene der ColumnGroup benötigen.

Entwurf 2: Angleichung physischer Dateien durch Zeilen-IDs

Hybride Dateiformate lösen ein Problem: Verschiedene Spalten können jetzt in den Formaten leben, die am besten zu ihnen passen.

Aber das schafft ein zweites Problem. Wenn skalare Felder in Parquet, Vektoren in Vortex und rohe Objekte in Objektspeicher leben, wie behandelt das System sie dann noch als eine Sammlung?

Loon löst dieses Problem mit der Ausrichtung der Zeilen-ID.

Row ID ist das Koordinatensystem der Speicherebene

Jede physische ColumnGroupFile speichert den Dateipfad und den Zeilen-ID-Bereich, den sie abdeckt:

path
start_index
end_index

Verschiedene ColumnGroups können denselben Row-ID-Bereich abdecken, auch wenn sie in unterschiedlichen Dateien und Formaten vorliegen.

Bei der Zeilen-ID 12345 können die skalaren Metadaten in einer Parquet ColumnGroup, die Einbettung in einer Vortex ColumnGroup und das Rohvideo in einer Objektspeicherreferenz enthalten sein. Logisch gesehen handelt es sich immer noch um eine Zeile. Dadurch erhält die Speicherebene ein stabiles Koordinatensystem.

Die Zeilen-ID ist nicht der geschäftliche Primärschlüssel. Es ist das Koordinatensystem der Speicherebene, das es Loon ermöglicht, eine Sammlung physisch aufzuteilen, ohne die Fähigkeit zu verlieren, sie logisch zu rekonstruieren.

Neue Spalten müssen alte Spalten nicht umschreiben

Das Hinzufügen von embedding_v2 erfordert kein Umschreiben der ursprünglichen Beschriftung, Metadaten oder embedding_v1 ColumnGroups. Loon kann eine neue Vektor-ColumnGroup schreiben, den Zeilen-ID-Bereich aufzeichnen, den sie abdeckt, und diese Änderung über das Manifest festschreiben.

Dasselbe gilt für spärliche Vektoren, Rerank-Features oder andere abgeleitete Felder, die später hinzukommen.

Solange die neue ColumnGroup den richtigen Zeilen-ID-Bereich abdeckt, kann sie der gleichen logischen Auflistung beitreten, ohne dass nicht zugehörige Daten verschoben werden müssen.

Löschungen und Verdichtungen können gezielter erfolgen

Die Ausrichtung von Zeilen-IDs hilft auch bei Löschungen.

Ein Löschvorgang kann zunächst durch ein Löschprotokoll ausgedrückt werden. Die Zeile wird auf der logischen Ebene unsichtbar, während die physische Bereinigung bis zur Verdichtung verzögert wird. Wenn die Verdichtung schließlich läuft, muss nicht immer jede ColumnGroup, die mit den betroffenen Zeilen verbunden ist, neu geschrieben werden. Sie kann sich auf die ColumnGroups konzentrieren, die bereinigt werden müssen.

Dies ist wichtig, weil nicht jede Spalte das gleiche Kostenprofil hat. Das Umschreiben einer kurzen skalaren ColumnGroup ist etwas ganz anderes als das Umschreiben von Hunderten von Gigabytes an dichten Vektoren.

Die hybride Suche kann nur die Spalten abrufen, die sie benötigt.

Der Abgleich von Zeilen-IDs macht die hybride Suche auch bei hybriden Dateiformaten sinnvoll.

Nachdem die ANN-Suche Kandidatenzeilen-IDs zurückgegeben hat, kann das System nur die Felder abrufen, die für das Endergebnis benötigt werden: Beschriftungen, Metadaten, Vektoren, Rerank-Features oder Objektreferenzen.

Zum Beispiel kann eine Abfrage erforderlich sein:

caption
embedding
video_uri

Diese Felder können sich in verschiedenen ColumnGroups befinden. Loon kann die relevanten Dateien anhand des Zeilen-ID-Bereichs lokalisieren, die erforderlichen Byte-Bereiche lesen und das Ergebnis zusammenstellen.

Ohne Row ID Alignment wären Hybridformate nur separate Dateien, die nebeneinander liegen. Mit Row ID Alignment verhalten sie sich wie eine einzige logische Sammlung.

Packed Reader verbirgt die Aufteilung vor der oberen Schicht

Die Laufzeitkomponente, die dies nutzbar macht, ist der Packed Reader.

Die obere Schicht sieht einen vereinheitlichten Arrow RecordBatch Stream. Darunter können die Daten aus mehreren ColumnGroups in unterschiedlichen Dateiformaten stammen. Der Packed Reader verbirgt diese Unterschiede, richtet die Daten nach Zeilen-ID-Bereichen aus und plant die E/A mehrerer Dateien mit kontrollierter Speichernutzung.

Er unterstützt auch die direkte take nach Zeilen-ID. Ausgehend von einer Reihe von Zeilen-IDs werden die entsprechenden ColumnGroupFiles gesucht, Lesebereiche ausgegeben und die angeforderten Felder zurückgegeben.

Für den Video-Workflow benötigt eine ANN-Abfrage möglicherweise caption, embedding und video_uri. Der Packed Reader kann die skalare ColumnGroup und die vektorielle ColumnGroup abrufen, ohne unverbundene Spalten zu berühren.

Das ist der Unterschied zwischen "getrennten Dateien" und "einer Tabelle mit mehreren physischen Layouts".

Entwurf 3: Das Manifest als Quelle der Wahrheit

Hybride Dateiformate definieren, wie die Daten physisch gespeichert werden. Die Ausrichtung der Zeilen-IDs bestimmt, wie getrennte ColumnGroups dennoch eine einzige logische Tabelle bilden. Aber das System muss noch eine größere Frage beantworten: Welche Dateien, Protokolle, Statistiken, Indizes und Objektreferenzen gehören zur aktuellen Version des Datensatzes? Das ist die Aufgabe des Manifests.

Objektspeicherverzeichnisse sind nicht genug

Ein Objektspeicher ist kein Datenbankkatalog. Ein Verzeichnis kann alte Dateien, neue Dateien, fehlgeschlagene Job-Outputs, temporäre Dateien, Löschprotokolle, Dateien, auf die noch von älteren Snapshots verwiesen wird, und Dateien, die auf die Bereinigung warten, enthalten. Die Tatsache, dass eine Datei existiert, bedeutet nicht, dass sie zur aktuellen Version des Datasets gehört.

Ein Loon-Datensatz kann in Verzeichnissen wie dem folgenden organisiert sein:

_metadata/
_data/
_delta/
_stats/
_index/

Aber die Verzeichnisstruktur ist nicht die Quelle der Wahrheit. Das Manifest ist es. Leser sollten keine Verzeichnisse auflisten und den Zustand aus den zufällig vorhandenen Dateien ableiten. Sie sollten das aktuelle Manifest lesen und der versionierten Ansicht folgen die es deklariert.

Das Manifest definiert eine versionierte Ansicht des Datensatzes

Das Manifest definiert den Datensatz in einer bestimmten Version. Es zeichnet auf:

  • welche ColumnGroups existieren
  • welche Zeilen-ID-Bereiche sie abdecken
  • welches physische Format jede ColumnGroup verwendet
  • wo sich die Dateien befinden
  • welche Löschprotokolle aktiv sind
  • welche Statistiken verfügbar sind
  • welche Indizes existieren
  • welche externen Blobs referenziert werden
  • welche Spalten und Zeilenbereiche diese Statistiken oder Indizes abdecken

Bei jeder Aktualisierung wird eine neue Manifest-Version geschrieben. Ein Leser, der Version N öffnet, sieht eine stabile Ansicht des Datenbestands in Version N. Ein Autor kann Version N+1 vorbereiten, ohne Leser zu stören, die noch Version N verwenden.

Das Manifest verfolgt mehr als nur Tabellendateien

In Loon ist der Manifestkörper mit Apache Avro kodiert und in vier Hauptabschnitte gegliedert.

  • ColumnGroups beschreiben die Spalten, Formate, Dateien und Zeilen-ID-Bereiche.
  • DeltaLogs beschreiben Löschvorgänge. Verschiedene Löschtypen decken unterschiedliche Änderungsquellen ab, z. B. Primärschlüssel-Löschungen von Clients, Positionslöschungen von der internen Verdichtung oder Gleichheitslöschungen von externen Engines.
  • Statistiken enthalten Planungsmetadaten wie Bloom-Filter, BM25-Statistiken und Min/Max-Werte.
  • Indizes beschreiben Index-Typ, Parameter, abgedeckte Spalten und Zeilen-ID-Bereiche. Dies kann Vektorindizes wie HNSW oder IVF, Textindizes, invertierte Indizes, Bitmap-Indizes und verwandte Strukturen umfassen.

Darin unterscheidet sich Loon von einem herkömmlichen Tabellenmanifest.

Ein Vektordatensatz muss nicht nur Datendateien und Partitionen verfolgen. Es muss auch Vektorindizes, Textindizes, Sparse Features, Löschprotokolle, Statistiken, externe Objektreferenzen und die Zeilen-ID-Bereiche, die sie verbinden, verfolgen.

Das Manifest muss nicht nur von der Datenbank beschreibbar sein

Der wichtigste Teil ist nicht nur, was das Manifest enthält. Es geht darum, wer es schreiben kann.

  • Wenn nur die Datenbank das Manifest schreiben kann, bleiben es interne Metadaten. Sauberere Metadaten, aber immer noch privat für eine Engine.
  • Wenn externe Engines neue ColumnGroups, Statistiken und Manifest-Einträge erzeugen können, wird das Manifest zu einer Koordinationsschnittstelle.
  • Ein Spark-Auftrag kann zum Beispiel eine spärliche Vektorspalte auffüllen. Er schreibt eine neue ColumnGroup, zeichnet Zeilenabdeckung und Statistiken auf und überträgt ein neues Manifest. Online-Abfragen können während des Jobs weiterhin die alte Version lesen. Sobald die Übertragung erfolgreich war, wird die neue Version sichtbar.

Diese Methode ähnelt Iceberg und Delta Lake, aber das Objektmodell ist breiter angelegt. Ein Vektordatensatz muss Vektorindizes, Textindizes, Sparse Features, Löschprotokolle, Statistiken, Blob-Referenzen und Zeilen-ID-Bereiche verfolgen, nicht nur Tabellendateien und Partitionen.

Optimistische Übertragungen halten Versionsaktualisierungen einfach

Jeder Commit schreibt eine neue Manifest-Version. Ein Writer kann neue Inhalte basierend auf Version N erstellen und dann versuchen, manifest-{N+1}.avro zu schreiben. Die Semantik des Objektspeichers für bedingtes Schreiben oder Generierung kann dazu führen, dass der Commit fehlschlägt, wenn diese Version bereits existiert. Der Writer kann es dann mit der neueren Version erneut versuchen.

Dies gibt Loon optimistische Gleichzeitigkeit, ohne jede Aktualisierung durch einen schweren, stark konsistenten Koordinationspfad zu zwingen. Ohne ein Manifest wird die Speicherung in mehreren Formaten und mit mehreren Maschinen schließlich zu einer Namenskonvention und einem manuellen Abgleich. Das mag für kleine Datensätze funktionieren. Bei Vektordaten im TB-Bereich funktioniert es nicht.

Erst das Manifest macht aus heterogenen Dateien einen Datensatz, den mehrere Systeme sicher lesen und aktualisieren können.

Was sich für die Nutzer ändert, wenn der Speicher versioniert wird

Für Anwendungsentwickler sollte Loon nicht zu einer neuen API-Belastung werden.

Die Benutzer sollten weiterhin mit vertrauten Milvus-Konzepten arbeiten: Sammlungen, Einfügungen, Suche und hybride Suche. Sie sollten sich während der normalen Anwendungsentwicklung keine Gedanken über Manifest-Dateien, ColumnGroups, Zeilen-ID-Bereiche oder Dateilayouts machen müssen.

Die Veränderung liegt darunter. Die Speicherung wird sich der tatsächlichen Entwicklung von KI-Datensätzen stärker bewusst.

Das Hinzufügen einer neuen Einbettung sollte die alten Daten nicht verschieben

Bisher war es für das Hinzufügen von embedding_v2 zu einer bestehenden Sammlung oft erforderlich, Daten zu exportieren, ein neues Modell zu trainieren, Vektoren zu generieren und die Sammlung dann über das SDK erneut zu importieren oder zu aktualisieren. Dieser Weg verursacht eine Menge betrieblicher Arbeit: Versionsverfolgung, fehlgeschlagene Job-Wiederholungen, Index-Neuaufbau, Serving Impact und Konsistenzprüfungen.

Mit Loon kann dies zu einer Schema-Evolution plus einem neuen ColumnGroup-Commit werden. Die neue Einbettungsspalte kann als eigene physische ColumnGroup geschrieben, nach Zeilen-ID ausgerichtet und über das Manifest sichtbar gemacht werden. Die alte Beschriftungsspalte, die skalare Metadatenspalte und die ursprüngliche Einbettungsspalte müssen nicht verschoben werden.

Backfills sollten keine clientseitige Aktualisierungsschleife erfordern

Viele AI-Datenaktualisierungen sind Backfills. Ein Team kann spärliche Vektoren hinzufügen, nachdem die hybride Suche wichtig geworden ist. Es kann Rerank-Features hinzufügen, nachdem ein neues Modell trainiert wurde. Es kann Beschriftungen nach einer menschlichen Überprüfung korrigieren. Es kann Governance-Tags nach einer Richtlinienaktualisierung hinzufügen.

In einem herkömmlichen Layout erfolgen diese Änderungen oft über Client-SDK-Updates oder reine Datenbank-Schreibpfade, selbst wenn die Daten von Spark, Ray oder einer anderen externen Engine erzeugt werden.

Mit Loon können externe Rechensysteme neue ColumnGroups erstellen und diese über das Manifest übertragen. Die Datenbank muss nicht mehr der einzige Einstiegspunkt für jeden Rewrite sein.

Offline-Analyse sollte keine weitere Kopie der Wahrheit erfordern

Früher haben Teams oft eine Online-Sammlung zur Offline-Auswertung oder -Analyse in Parquet abgelegt. Dadurch wurden zwei Versionen desselben Datensatzes erstellt: die Online-Sammlung und die Analysekopie. Sobald Beschriftungen korrigiert, Einbettungen neu generiert, Löschprotokolle angewendet oder Indizes neu erstellt werden, muss sich das Team fragen, welche Kopie aktuell ist.

Mit einem Manifest-basierten Speichermodell können Analyse-Engines die gleiche versionierte Datensatzansicht lesen wie das Serving-System. Sie können nur die benötigten Spalten projizieren, nur die relevanten Zeilenbereiche scannen und mit einer deklarierten Version des Datensatzes arbeiten, anstatt mit einem manuell exportierten Snapshot.

Löschungen und Korrekturen sollten nur das betreffen, was sich geändert hat

Löschungen, Beschriftungskorrekturen, Korrekturen von Bezeichnungen und Aktualisierungen der Governance sind in AI-Datensätzen Routine. Sie sollten nicht jede lange Vektorspalte durch denselben Rewrite-Pfad zwingen.

Mit Loon kann das Löschen von Protokollen zunächst als logische Löschung behandelt werden. Eine spätere Verdichtung kann die betroffenen ColumnGroups bereinigen, ohne dass nicht zugehörige Daten neu geschrieben werden. Wenn sich ein kurzes Textfeld ändert, sollte die Speicherschicht nicht Hunderte von Gigabyte dichter Vektoren neu schreiben müssen, nur weil sie dieselbe logische Zeile teilen.

Externe Engines werden Teil des Arbeitsablaufs, nicht eine Fluchtluke

Die größere Veränderung besteht darin, dass externe Engines nicht mehr als Systeme außerhalb der Vektordatenbank behandelt werden.

Spark, Ray, Auswertungsjobs, Beschriftungssysteme und Governance-Pipelines erzeugen und verändern bereits einen Großteil der Daten. Die Speicherebene sollte es ihnen ermöglichen, um eine einzige Quelle der Wahrheit herum zusammenzuarbeiten, anstatt ständig zu exportieren, zu kopieren und wieder zu importieren.

Das ist es, was eine Version von Manifest ermöglicht. Es bietet Online-Serving, Offline-Analyse, Backfill-Jobs und Verdichtung eine gemeinsame Ansicht des Datensatzes.

Dies mag wie interne Speicherdetails klingen, hat aber Auswirkungen darauf, wie schnell Teams KI-Datensätze iterieren können. Jede Modelländerung, jedes Backfill von Merkmalen, jede Korrektur von Beschriftungen, jeder Qualitätsfilter und jeder Indexneuaufbau hängt von der gleichen Frage ab: "Kann das System den Datensatz aktualisieren, ohne Daten zu verschieben, die nicht verschoben werden müssen?"

Das ist der praktische Wert des Speichermodells.

Loon ist in Milvus 3.0 beta und Zilliz Vector Lakebase verfügbar

Loon ist in Milvus 3.0 beta verfügbar und ist auch Teil der Speicherschicht in Zilliz Vector Lakebase, der nächsten Evolution von Zilliz Cloud. Und diese Version konzentriert sich auf drei Kernbereiche:

  • Das Manifest. Ziel ist es, dass Schreibvorgänge, Backfills, Löschvorgänge, Statistiken und Index-Updates versionierte Datensatzansichten erzeugen, die Leser konsistent öffnen können. Für Leser bedeutet dies, dass eine Abfrage eine bestimmte Manifestversion öffnen kann und eine stabile Ansicht des Datensatzes angezeigt wird. Für Autoren bedeutet dies, dass neue Datendateien, Löschprotokolle, Statistiken oder Indexdateien zunächst vorbereitet und dann durch eine versionierte Übergabe sichtbar gemacht werden können.
  • Die ColumnGroup und die Formatunterstützung. Parquet unterstützt skalare und ökosystemfreundliche Spalten. Vortex unterstützt vektorlastige Zugriffsmuster. Lance kann im Nur-Lese-Modus integriert werden, um die Kompatibilität mit bestehenden Lance-Datensätzen zu gewährleisten.
  • Der Index auf Lake. Skalare Statistiken, filternde Indizes und textinvertierte Indizes können an der Manifest-basierten Planung nach Zeilenbereich teilnehmen. Lake-native Vektorindizes sind komplizierter. HNSW und IVF haben ein unterschiedliches Verhalten bei der Speicherung von Objekten, und insbesondere HNSW reagiert empfindlich auf zufälligen Zugriff und Cache-Lokalität. Es kann nicht einfach ein für eine lokale SSD entworfenes Layout wiederverwenden und das gleiche Ergebnis erwarten.

Es gibt noch viel zu tun

  • Externe Schreibpfade sind wichtig, da Spark und Ray in der Lage sein sollten, ColumnGroups und Manifest-Commits zu erzeugen, ohne jeden Backfill durch eine Client-SDK-Schleife zu zwingen.
  • Lakehouse-Interoperabilität ist wichtig, da viele Teams bereits Kataloge und Abfrage-Engines wie Iceberg, Delta Lake, Trino, DuckDB und Athena verwenden . Vektordaten sollten in der Lage sein, an diesem Ökosystem teilzunehmen, ohne dass die Vektorsuchleistung darunter leidet.
  • DasIndex-Layout ist wichtig, da Graphenindizes und invertierte Strukturen unterschiedliche Zugriffsmuster auf Objektspeicher haben.
  • Die Semantik großer Objekte ist wichtig, da Rohvideos, PDFs, Bilder und Audiodateien ein Referenzmanagement, eine Versionierung und ein Löschverhalten erfordern, das mit dem abgeleiteten Vektordatensatz übereinstimmt.

Das genaue Freigabeverhalten, die Standardeinstellungen und der Migrationspfad sollten den entsprechenden Milvus- und Zilliz Cloud-Versionshinweisen folgen. Die Richtung der Speicherung ist jedoch klar: Vektordatenbanken benötigen eine versionierte, lake-native Grundlage unterhalb der Serving-Schicht.

Versuchen Sie Loon unter Zilliz Vector Lakebase

Wenn Ihr aktueller Stack Online-Serving, Offline-Analyse, Backfills und externe Data-Lake-Workflows in verschiedene Systeme aufteilt, ist Zilliz Vector Lakebase einen Blick wert. Sie können es in Zilliz Cloud ausprobieren. Wer sich per E-Mail neu anmeldet, erhält $100 Gratis-Credits. Sie sind auch herzlich eingeladen, mit uns über Ihren Anwendungsfall zu sprechen.

Sie können auch die Veröffentlichung von Milvus 3.0 verfolgen, um zu sehen, wie sich Loon in der Open-Source-Engine weiterentwickelt.

Zilliz Vector Lakebase bringt zusammen:

  • Tiered Serving für unterschiedliche Echtzeit-Performance und Kostenabwägungen
  • On-Demand-Suche für große oder explorative Workloads ohne permanente Rechenleistung
  • Externe Data-Lake-Suche, so dass Sie direkt über vorhandene Lake-Daten indizieren und suchen können
  • Vollspektrum-Suche über Vektoren, Text, JSON und Geodaten, mit hybrider Suche und Reranking
  • Einheitlicher Lake-nativer Speicher auf Basis von Vortex, einem offenen Format, das für schnellere, kostengünstigere Zufallslesevorgänge bei vektorlastigen Daten entwickelt wurde

    Try Managed Milvus for Free

    Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

    Get Started

    Like the article? Spread the word

    Weiterlesen