Skip to content
BotServBotServ
MilvusVektordatenbankSkalierungIVFHNSWRAGlokale KI

Milvus: Vektordatenbank für große Skalierung

Milvus Vektordatenbank: Installation, Index-Typen, Skalierung und Nutzung für RAG. Hochperformante Vektor-Suche mit Beispielen.

S

schutzgeist

11 min read
Milvus Vektordatenbank

Milvus: Vektordatenbank für große Skalierung

Was dieser Artikel behandelt

  • Was Milvus ist und warum es sich für große Datenmengen besonders eignet
  • Wie Du Milvus mit Docker lokal installierst und betreibst
  • Welche Index-Typen es gibt und wie Du den richtigen für Deinen Anwendungsfall wählst
  • Wie Du mit pymilvus Daten speicherst, suchst und filterst
  • Wie sich Milvus im Vergleich zu Chroma und Qdrant schlägt und wann es die richtige Wahl ist

Einleitung

Du hast lokales RAG für Dich entdeckt und vielleicht schon erste Erfahrungen mit Chroma oder Qdrant gesammelt. Jetzt stehst Du vor der Frage: Was passiert, wenn Deine Dokumentensammlung wächst und wächst? Wenn es nicht mehr um Tausende, sondern um Millionen von Vektoren geht?

Genau hier kommt Milvus ins Spiel. Milvus ist eine Open-Source-Vektordatenbank, die speziell für große Skalierung und hohe Performance entwickelt wurde. Sie unterstützt verschiedene Index-Typen, kann verteilt betrieben werden und geht mit Datenmengen um, die andere Datenbanken an ihre Grenzen bringen.

Dieser Artikel führt Dich durch die Installation, die Index-Auswahl, die Datenspeicherung und die Suchanfragen. Wenn Du die RAG Grundlagen noch nicht kennst, lies Dir diesen Artikel zuerst durch. Grundwissen zu Embedding-Modellen ist ebenfalls empfehlenswert.

Warum brauche ich Milvus?

Stell Dir vor, Du betreibst eine RAG-Anwendung für ein großes Unternehmen. Die Wissensbasis umfasst Hunderttausende von Dokumenten, und jeden Tag kommen neue hinzu. Die Vektordatenbank muss nicht nur all diese Vektoren speichern, sondern auch in Millisekunden die ähnlichsten finden.

Mit Chroma stößt Du bei solchen Datenmengen an Grenzen. Qdrant kommt deutlich weiter, ist aber primär für einzelne Knoten optimiert. Milvus hingegen ist von Grund auf für verteilte Architektur gebaut. Du kannst mit mehreren Knoten arbeiten, Daten über mehrere Maschinen verteilen und trotzdem schnelle Suchergebnisse erhalten.

Ein weiterer Pluspunkt ist die Auswahl an Index-Typen. Milvus unterstützt IVF, HNSW, DiskANN und mehrere weitere. Jeder Index-Typ hat eigene Stärken: manche sind schneller beim Aufbau, andere brauchen weniger Speicher, wieder andere sind optimal für sehr große Datenmengen. Du wählst den Index, der zu Deinem Anwendungsfall passt, statt Dich auf eine Einheitslösung festzulegen.

Für lokale Setups musst Du nicht zwingend einen verteilten Cluster aufbauen. Milvus Lite und Milvus Standalone reichen für die meisten Projekte völlig aus. Aber wenn Dein Projekt wächst, kannst Du auf Milvus Distributed upgraden, ohne die Datenbank zu wechseln.

Milvus kurz erklärt

Milvus speichert Vektoren in sogenannten Collections, vergleichbar mit Tabellen in einer relationalen Datenbank. Jede Collection hat ein Schema, das die Felder und deren Datentypen definiert. Eines dieser Felder ist der primäre Vektor, der für die Ähnlichkeitssuche genutzt wird.

Bei einer Suchanfrage wandelt Milvus die Anfrage in einen Vektor um und durchsucht den Index der Collection. Der Index ist eine Datenstruktur, die die Suche beschleunigt, indem sie nicht jeden Vektor einzeln vergleicht, sondern geschickt gruppiert und vorfiltert. Welchen Index Du wählst, beeinflusst die Suchgeschwindigkeit, den Speicherbedarf und die Genauigkeit der Ergebnisse.

Milvus läuft in drei Modi: Milvus Lite für Tests direkt in Python, Milvus Standalone als einzelner Docker-Container und Milvus Distributed als Cluster mit mehreren Knoten. Für lokale RAG-Projekte empfiehlt sich Milvus Standalone, weil es einfach einzurichten ist und trotzdem alle wichtigen Funktionen bietet.

Für wen ist dieser Artikel gedacht?

Dieser Artikel richtet sich an Entwickler, die bereits grundlegend mit RAG und Vektordatenbanken vertraut sind. Du solltest verstehen, was lokale KI ist und wie RAG funktioniert. Wenn Du Chroma oder Qdrant ausprobiert hast und nach einer Lösung für größere Datenmengen suchst, ist dieser Artikel der richtige nächste Schritt. Du brauchst grundlegende Python-Kenntnisse und solltest wissen, wie man Docker bedient.

Wichtige Begriffe

BegriffErklärung
CollectionEin Behälter für Vektoren und Metadaten, vergleichbar mit einer Tabelle.
SchemaDie Definition der Felder, Datentypen und Vektor-Parameter einer Collection.
IndexEine Datenstruktur, die die Vektorsuche beschleunigt, etwa IVF oder HNSW.
IVFInverted File Index, gruppiert Vektoren in Cluster und beschleunigt die Suche.
HNSWHierarchical Navigable Small World, ein Graph-basierter Index für sehr schnelle Suche.
DiskANNEin Index, der Daten auf der Festplatte hält und für sehr große Datenmengen optimiert ist.
Metric TypeDie Distanzmetrik für die Ähnlichkeitssuche, etwa Cosine, L2 oder IP.
PartitionEine Unterteilung einer Collection, um Suchen auf Teilbereiche einzugrenzen.
SegmentDie physische Speichereinheit in Milvus, in der Daten organisiert werden.

Installation: Milvus Standalone mit Docker

Milvus Standalone ist die beste Wahl für lokale Projekte. Es läuft in einem einzelnen Docker-Container und benötigt etcd und MinIO als Abhängigkeiten. Am einfachsten nutzt Du die offizielle docker-compose.yml-Datei von Milvus.

Lade die Datei herunter und starte den Dienst:

wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
docker compose up -d

Nach dem Start überprüfst Du, ob alle Container laufen:

docker compose ps

Du solltest drei laufende Container sehen: milvus, etcd und minio. Milvus ist unter dem Port 19530 erreichbar. Wenn Du Docker noch nicht installiert hast, schau Dir die Docker Grundlagen an.

Alternativ kannst Du Milvus Lite nutzen, das ohne Docker direkt in Python läuft. Das ist ideal für Tests, aber nicht für produktive Anwendungen geeignet:

pip install pymilvus

Mit Milvus Lite brauchst Du keinen Server, sondern nutzt Milvus als eingebettete Bibliothek. Für diesen Artikel verwenden wir Milvus Standalone mit Docker, weil es näher an einem echten Produktionssystem ist.

Python-Client installieren

Der Python-Client für Milvus heißt pymilvus. Installiere ihn mit pip:

pip install pymilvus

Danach verbindest Du Dich in Python mit Deiner lokalen Milvus-Instanz:

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

print(client.list_collections())  # Zeigt alle vorhandenen Collections

Wenn Du Milvus Lite nutzt, gibst Du statt der URI einen Dateipfad an:

client = MilvusClient(uri="./milvus.db")

Collection anlegen und Schema definieren

Bevor Du Daten speicherst, legst Du eine Collection an. In Milvus definierst Du die Felder des Schemas explizit. Jede Collection braucht mindestens ein primäres Schlüsselfeld und ein Vektorfeld.

from pymilvus import MilvusClient, DataType

client.create_collection(
    collection_name="articles",
    fields=[
        {"name": "id", "dtype": DataType.INT64, "is_primary": True},
        {"name": "title", "dtype": DataType.VARCHAR, "max_length": 200},
        {"name": "content", "dtype": DataType.VARCHAR, "max_length": 2000},
        {"name": "source", "dtype": DataType.VARCHAR, "max_length": 100},
        {"name": "vector", "dtype": DataType.FLOAT_VECTOR, "dim": 768}
    ]
)

Das Vektorfeld vector hat die Dimension 768, was dem Output von intfloat/multilingual-e5-large entspricht. Wenn Du ein anderes Embedding-Modell nutzt, passe die Dimension entsprechend an.

Index erstellen

Nach dem Anlegen der Collection erstellst Du einen Index für das Vektorfeld. Der Index ist entscheidend für die Suchgeschwindigkeit. Ohne Index würde Milvus jeden Vektor einzeln durchsuchen, was bei großen Datenmengen zu langsam ist.

client.create_index(
    collection_name="articles",
    field_name="vector",
    index_type="IVF_FLAT",
    metric_type="COSINE",
    params={"nlist": 128}
)

Der Parameter nlist gibt an, in wie viele Cluster die Vektoren gruppiert werden. Ein höherer Wert bedeutet feinere Cluster und genauere Ergebnisse, aber mehr Speicherbedarf. Ein guter Startwert ist 128 bis 1024, je nach Datenmenge.

Index-Typen im Vergleich

Milvus bietet mehrere Index-Typen. Hier ist eine Übersicht der wichtigsten:

IVF_FLAT: Gruppiert Vektoren in Cluster und durchsucht nur die relevanten. Einfach einzurichten, gut für mittlere Datenmengen. Der Speicherbedarf ist moderat, die Genauigkeit hoch.

IVF_SQ8: Wie IVF_FLAT, aber mit quantisierten Vektoren. Reduziert den Speicherbedarf auf etwa ein Viertel, bei leicht geringerer Genauigkeit. Gut, wenn Speicherplatz knapp ist.

HNSW: Ein Graph-basierter Index mit mehreren Hierarchieebenen. Sehr schnelle Suche und hohe Genauigkeit, aber höherer Speicherbedarf und langsamerer Aufbau. Ideal für Anwendungen, bei denen Suchgeschwindigkeit wichtiger ist als Speicherplatz.

DiskANN: Hält den Index auf der Festplatte statt im RAM. Perfekt für sehr große Datenmengen, die nicht in den Arbeitsspeicher passen. Die Suche ist etwas langsamer als bei HNSW, aber die Speichereffizienz ist unschlagbar.

Für die meisten lokalen RAG-Projekte ist HNSW die beste Wahl, weil es die schnellsten Suchergebnisse liefert und die Datenmengen meist in den RAM passen. Wenn Deine Daten wachsen und der RAM nicht mehr ausreicht, wechsle zu DiskANN.

Daten speichern

Jetzt fügen wir Daten zur Collection hinzu. Du übergibst die Vektoren zusammen mit den Metadatenfeldern.

data = [
    {
        "id": 1,
        "title": "Was ist lokale KI?",
        "content": "Lokale KI läuft auf dem eigenen Rechner ohne Cloud-Dienste.",
        "source": "blog",
        "vector": [0.12, 0.34, 0.56] + [0.0] * 765  # Auf 768 Dimensionen aufgefüllt
    },
    {
        "id": 2,
        "title": "RAG erklärt",
        "content": "RAG verbindet Dokumentensuche mit Sprachmodellen.",
        "source": "blog",
        "vector": [0.23, 0.45, 0.67] + [0.0] * 765
    }
]

client.insert(collection_name="articles", data=data)

In der Praxis erzeugst Du die Vektoren mit einem echten Embedding-Modell. Die obigen Vektoren sind Platzhalter. Wichtig ist, dass jeder Vektor genau die Dimension hat, die im Schema definiert wurde.

Suchanfragen durchführen

Nachdem Du Daten gespeichert und einen Index erstellt hast, kannst Du Suchanfragen stellen. Milvus lädt die Collection vorher in den Speicher:

client.load_collection(collection_name="articles")

results = client.search(
    collection_name="articles",
    data=[[0.15, 0.40, 0.60] + [0.0] * 765],  # Suchvektor
    limit=3,
    output_fields=["title", "content", "source"]
)

for hits in results:
    for hit in hits:
        print(hit["entity"]["title"], hit["distance"])

Der Parameter limit gibt an, wie viele Ergebnisse Du zurückbekommst. output_fields steuert, welche Felder im Ergebnis enthalten sind. Die distance zeigt, wie ähnlich der gefundene Vektor dem Suchvektor ist.

Filterung

Milvus unterstützt Filterausdrücke, um Suchergebnisse einzuschränzen. Das ist wichtig, wenn Du nur bestimmte Quellen oder Kategorien durchsuchen willst.

results = client.search(
    collection_name="articles",
    data=[[0.15, 0.40, 0.60] + [0.0] * 765],
    limit=3,
    filter='source == "blog"',
    output_fields=["title", "content", "source"]
)

for hits in results:
    for hit in hits:
        print(hit["entity"]["title"], hit["entity"]["source"])

Filterausdrücke in Milvus nutzen eine SQL-ähnliche Syntax. Du kannst Vergleiche, logische Operatoren und Bereichsabfragen kombinieren. Das ist flexibler als einfache Metadaten-Filter in anderen Datenbanken.

Vergleich: Milvus vs. Chroma vs. Qdrant

EigenschaftMilvusChromaQdrant
SkalierungSehr hoch, verteilt möglichEher klein bis mittelHoch, einzelne Knoten
Index-TypenIVF, HNSW, DiskANN und mehrHNSW (intern)HNSW
ArchitekturVerteilt, mit etcd und MinIOEingebettet oder ServerServer, einzelner Prozess
RessourcenbedarfMittel bis hochNiedrigNiedrig bis mittel
EinstiegshürdeMittelSehr niedrigNiedrig
FilterSQL-ähnliche AusdrückeEinfachSehr mächtig
PerformanceSehr hoch bei großen DatenmengenGut bei kleinen MengenSehr hoch
Setup-AufwandHöher, mehrere ContainerMinimalGering

Milvus glänzt, wenn Du große Datenmengen verwalten musst und eine Datenbank suchst, die mitwächst. Chroma ist ideal für den schnellen Start, Qdrant ist ein starker Allrounder. Milvus lohnt sich, wenn Du planst, langfristig mit Millionen von Vektoren zu arbeiten.

Typische Stolpersteine

  1. Collection nicht laden: Milvus verlangt, dass Du eine Collection in den Speicher lädst (load_collection), bevor Du suchen kannst. Wenn Du das vergisst, bekommst Du einen Fehler. Nach dem Einfügen neuer Daten musst Du die Collection nicht neu laden, aber bei Index-Änderungen schon.
  2. Falsche Vektor-Dimension: Die Dimension im Schema muss exakt mit Deinem Embedding-Modell übereinstimmen. Ein falscher Wert führt zu Fehlern beim Einfügen. Prüfe die Dimension Deines Modells, bevor Du das Schema anlegst.
  3. Index vor Daten erstellen: Der Index sollte erstellt werden, bevor Du große Datenmengen einfügst. Wenn Du erst Daten einfügst und dann den Index erstellst, dauert der Indexaufbau länger.
  4. Metric Type verwechseln: Wenn Dein Embedding-Modell für Cosine-Distanz optimiert ist, Du aber L2 nutzt, bekommst Du schlechte Suchergebnisse. Prüfe, welche Metrik Dein Modell empfiehlt.
  5. etcd und MinIO vergessen: Milvus Standalone braucht etcd und MinIO. Wenn Du nur den Milvus-Container startest, funktioniert nichts. Nutze immer die offizielle docker-compose.yml-Datei.
  6. Persistenz nicht konfiguriert: Standardmäßig speichert Milvus Daten in Volumes, die in der docker-compose.yml-Datei definiert sind. Wenn Du diese Datei anpasst, stelle sicher, dass die Volumes erhalten bleiben.
  7. Zu viele Ergebnisse abfragen: Bei großen Collections kann limit mit einem hohen Wert die Performance verschlechtern. Beginne mit kleinen Werten und erhöhe nur bei Bedarf.
  8. Partitionen nicht nutzen: Bei sehr großen Collections kannst Du Partitionen nutzen, um Suchen auf Teilbereiche einzugrenzen. Das verbessert die Performance erheblich, wird aber oft übersehen.

Hardware, Kosten und Sicherheit

Milvus Standalone benötigt mindestens 8 GB RAM, um vernünftig zu funktionieren. Für größere Datenmengen sind 16 GB oder mehr empfehlenswert. Der Speicherbedarf auf der Festplatte hängt von der Datenmenge und dem Index-Typ ab: HNSW braucht mehr Speicher als IVF_SQ8, und DiskANN nutzt die Festplatte effizienter als RAM-basierte Indizes.

Milvus ist Open Source und kostenlos. Die Community Edition deckt alle Funktionen ab, die Du für lokale RAG-Projekte brauchst. Es gibt auch eine kommerzielle Cloud-Version namens Zilliz Cloud, die für lokale Setups nicht relevant ist.

Sicherheitstechnisch gilt dasselbe wie für andere lokale Datenbanken: Solange Milvus nur im eigenen Netzwerk erreichbar ist, sind Deine Daten geschützt. Wenn Du Milvus über das Netzwerk zugänglich machst, nutze einen Reverse Proxy mit TLS und aktiviere Authentifizierung. Da alle Daten lokal bleiben, ist das ein großer Vorteil gegenüber Cloud-basierten Vektordatenbanken, wie im Artikel zu lokaler KI vs. Cloud-KI erläutert.

FAQ

Muss ich einen verteilten Cluster aufbauen, um Milvus zu nutzen?

Nein. Milvus Standalone reicht für die meisten lokalen Projekte völlig aus. Der verteilte Modus ist nur nötig, wenn Deine Datenmengen so groß sind, dass ein einzelner Knoten nicht mehr ausreicht.

Was ist der Unterschied zwischen Milvus Lite und Milvus Standalone?

Milvus Lite läuft direkt in Python ohne Docker und ist ideal für Tests. Milvus Standalone läuft als Docker-Setup mit etcd und MinIO und ist näher an einem Produktionssystem. Für ernsthafte Projekte nutze Milvus Standalone.

Ist Milvus kostenlos?

Ja, die Open-Source-Version ist kostenlos. Es gibt eine kommerzielle Cloud-Version namens Zilliz Cloud, die für lokale Setups nicht nötig ist.

Wie viele Vektoren verträgt Milvus lokal?

Das hängt von RAM und Speicherplatz ab. Milvus ist für Millionen von Vektoren ausgelegt. Mit DiskANN kannst Du sogar Datenmengen verarbeiten, die nicht in den RAM passen.

Kann ich Milvus mit Ollama verbinden?

Ja. Ollama liefert das Sprachmodell, Milvus die Vektordatenbank. Dein Python-Skript verbindet beide: Milvus findet die relevanten Dokumente, Ollama generiert die Antwort.

Welchen Index-Typ soll ich wählen?

Für die meisten lokalen RAG-Projekte ist HNSW die beste Wahl, weil es die schnellsten Suchergebnisse liefert. Wenn der RAM nicht ausreicht, wechsle zu DiskANN. Für kleine Datenmengen reicht IVF_FLAT.

Brauche ich Docker für Milvus?

Für Milvus Standalone ja, weil etcd und MinIO als zusätzliche Container laufen. Für Tests kannst Du Milvus Lite ohne Docker nutzen.

Unterstützt Milvus hybride Suche?

Ja, ab Version 2.4 unterstützt Milvus hybride Suche mit Sparse Vectors. Du kannst dichte und spärliche Vektoren kombinieren, um semantische und schlüsselwortbasierte Suche zu vereinen. Mehr dazu im Artikel zu Hybrid Search.

Kann ich Milvus auf einem NAS betreiben?

Ja, mit Docker. Achte auf ausreichend RAM und schnellen Speicher. Milvus profitiert stark von SSD-Speicher, besonders bei HNSW-Indizes.

Was ist der Unterschied zwischen Milvus und Qdrant?

Qdrant ist schlanker und einfacher einzurichten, ideal für mittlere Datenmengen. Milvus ist komplexer im Setup, aber besser für sehr große Datenmengen und verteilte Architektur geeignet.

Wie viel RAM brauche ich für Milvus?

Mindestens 8 GB für Milvus Standalone. Für größere Datenmengen mit HNSW sind 16 GB oder mehr empfehlenswert. Mit DiskANN kannst Du den RAM-Bedarf reduzieren, weil der Index auf der Festplatte liegt.

Quellen

  • Milvus offizielle Webseite: milvus.io
  • Milvus Dokumentation: milvus.io/docs
  • pymilvus auf GitHub: github.com/milvus-io/pymilvus
  • Milvus GitHub Repository: github.com/milvus-io/milvus
  • Artikel zu Vektordatenbanken in dieser Reihe
  • Artikel zu Hybrid Search in dieser Reihe
Zurück zum KI Blog
Share:

Ähnliche Beiträge