Startseite / Artikel / Jenseits von naivem RAG: HNSW-Speicherkosten, hybride Suche und langer Kontext

Jenseits von naivem RAG: HNSW-Speicherkosten, hybride Suche und langer Kontext

Warum In-Memory-Vektorindizes bei großen Datenmengen an eine Grenze stoßen, wo exakte Treffer scheitern und wie BM25-Hybride, RRF und PostgreSQL in eine Welt mit langem Kontext passen.

1175 Wörter

Kontextfenster reichen inzwischen bis zu einer Million Token und darüber hinaus, und das verändert still und leise, wofür Vektorsuche eigentlich da ist. Dieselbe Verschiebung zeigt, warum hochdimensionale Indizes bei großen Datenmengen Probleme bekommen, und deutet an, wohin sich Enterprise-Retrieval entwickelt.

Die einfachen Jahre von RAG

Als Retrieval-Augmented Generation zum Standardmuster für LLM-Anwendungen in Unternehmen wurde, sah das Rezept simpel aus:

  1. Den Korpus in Schnipsel unter 1.000 Token zerlegen.
  2. Jeden Schnipsel durch ein Embedding-Modell wie text-embedding-3-large schicken.
  3. Die dichten Vektoren in einer eigenen Vektordatenbank auf Basis von Hierarchical-Navigable-Small-World-Graphen (HNSW) ablegen.
  4. Zur Abfragezeit eine Approximate-Nearest-Neighbor-Suche (ANN) ausführen und die besten Treffer in den Prompt kopieren.

Mit 10.000 Dokumenten und einem 4k-Kontextfenster funktionierte das gut. Dann wuchsen die Fenster über 1M Token, und die Rechnung änderte sich. Wenn ein Engineer eine komplette Codebasis, ein Rechtsarchiv oder ein Jahr an Geschäftsberichten in den Prompt packen kann, verliert naive Vektorsuche an Überzeugungskraft.

Die Größenordnung bringt ein weiteres Problem mit. Sobald Datensätze von Millionen auf Milliarden Vektoren wachsen, werden drei versteckte Kosten reiner Vektorsuche sichtbar: erschöpfter Arbeitsspeicher, eine Indexqualität, die mit wachsender Dimension nachlässt, und eine semantische Trefferquote, die sich nicht vorhersagen lässt. Im Folgenden geht es darum, warum Vektordatenbanken an diese Grenzen stoßen und was Produktivsysteme heute tun.

Das Speicherproblem von HNSW

Fast jede große Vektor-Engine, darunter Pinecone, Qdrant, Milvus, Weaviate und pgvector, setzt auf HNSW-Graphen. HNSW ermöglicht schnelle logarithmische Suche, indem es Punkte in Schichten anordnet. Die oberen Schichten enthalten weite Verbindungen für schnelle Sprünge, die unteren dichte lokale Nachbarschaftsverbindungen.

Der Haken: Für eine schnelle Traversierung muss der Graph im RAM liegen.

Die Rechnung

Nehmen wir 1536-dimensionale Embeddings, wie sie text-embedding-3-small oder ada-002 von OpenAI liefern, gespeichert als 32-Bit-Floats. Jeder Vektor belegt 1536 mal 4 Byte, also 6.144 Byte, rund 6 KB.

Bei 100 Millionen Vektoren:

  • Rohvektoren: 100 Millionen mal 6 KB ergibt etwa 600 GB.
  • Graph-Overhead: Jeden Knoten mit 16 bis 64 Nachbarn zu verbinden, kostet weitere 20 bis 50 Prozent.
  • Gesamtspeicher: irgendwo zwischen 750 GB und 1 TB schnellem RAM.

Bei Cloud-Preisen kann es schnell teurer werden, ein Terabyte Speicher nur zum Indexieren von Textschnipseln zu mieten, als die LLM-Inferenz selbst.

Product Quantization (PQ) und skalare Quantisierung (SQ8) schrumpfen Vektoren von float32 auf int8 oder binäre Formen, bringen aber ein zweites Problem mit: Der Recall sinkt.

Der Fluch der Dimensionalität und semantischer Drift

Ab etwa 1000 Dimensionen zeigen Vektorräume geometrische Eigenheiten, die als Fluch der Dimensionalität bekannt sind. Eine davon ist die Distanzkonzentration. Mit steigender Dimension nähert sich das Verhältnis aus der Distanz zum nächsten Punkt und der Distanz zum entferntesten Punkt dem Wert 1.

Bei der Kosinus-Ähnlichkeit wirkt dann fast jeder Vektor von jedem anderen gleich weit entfernt. Kommt Quantisierung hinzu, verschwimmen die Grenzen zwischen unterschiedlichen Konzepten noch stärker.

Wo exakte Treffer scheitern

Vektorsuche ist von Natur aus probabilistisch. Sie misst Bedeutung, nicht wörtliche Token. In Unternehmenssystemen, in denen wörtliche Übereinstimmungen zählen, führt das zu ernsten Fehltreffern:

  • Teilenummern und Kennungen. Eine Suche nach "Part #AB-9941-X" kann "Part #AB-9942-X" liefern, weil beide Embeddings im selben Cluster landen.
  • Verneinung und Logik. Eine Anfrage wie "Contracts without liability caps" liefert oft gerade Verträge mit Haftungsbegrenzung, weil sich das Embedding-Modell an der Phrase „liability caps“ festbeißt.

Langer Kontext gegen Chunks

Mit Modellen, die große Fenster nativ verarbeiten, hat sich die Abwägung zwischen vorab indexieren und direkt im Kontext auswerten verschoben. Wer ein Dokument in Stücke zu 512 Token schneidet, kappt Querverweise, Tabellenabhängigkeiten und logische Bedingungen, die sich über die Seite erstrecken. Wenn ein großes Fenster ganze Dokumente aufnehmen kann, verliert naives Chunking seine Daseinsberechtigung, und Vektorsuche wandelt sich vom Finden von Schnipseln zum Routing großer Dokumentblöcke.

Hybride Suche und die Rückkehr von BM25

Um diese Grenzen zu umgehen, bewegt sich Data Engineering weg von reinen Vektorspeichern hin zu hybriden Architekturen aus drei Bausteinen:

  1. Dense Retrieval mit Vektoren, das allgemeine Absichten und semantische Fragen erfasst.
  2. Sparse Retrieval mit BM25 oder SPLADE, das exakte Schlüsselwörter, Seriennummern und konkrete Entitäten erfasst.
  3. Reciprocal Rank Fusion (RRF), die beide Ergebnislisten zusammenführt, bevor die Top-K-Kandidaten an ein Reranker-Modell gehen.

Eine Backend-Pipeline kann dichte und spärliche Scores per RRF in Python etwa so zusammenführen:

from typing import List, Dict

def reciprocal_rank_fusion(
    dense_results: List[str],
    sparse_results: List[str],
    k: int = 60
) -> List[Dict[str, float]]:
    """
    Combines dense vector search results and sparse BM25 search results
    using Reciprocal Rank Fusion (RRF).
    """
    rrf_scores: Dict[str, float] = {}

    # Score Dense Results
    for rank, doc_id in enumerate(dense_results):
        if doc_id not in rrf_scores:
            rrf_scores[doc_id] = 0.0
        rrf_scores[doc_id] += 1.0 / (k + (rank + 1))

    # Score Sparse Results (BM25)
    for rank, doc_id in enumerate(sparse_results):
        if doc_id not in rrf_scores:
            rrf_scores[doc_id] = 0.0
        rrf_scores[doc_id] += 1.0 / (k + (rank + 1))

    # Sort documents by descending fusion score
    sorted_docs = sorted(
        rrf_scores.items(), key=lambda item: item[1], reverse=True
    )

    return [{"doc_id": doc, "score": score} for doc, score in sorted_docs]

Warum relationale Datenbanken Workloads zurückgewinnen

Der Bedarf an hybrider Suche zieht Workloads zurück zu klassischen Datenbanken. Mit PostgreSQL (mit pgvector und pg_trgm), Elasticsearch und SingleStore laufen Vektorabfragen direkt neben operativen Metadaten, relationalen Joins und ACID-Transaktionen, ohne dass eine separate Vektordatenbank betrieben werden muss.

- PostgreSQL Hybrid Query: Vector Distance + Full Text Match + Relational Filter
SELECT
 id,
 title,
 (ts_rank(text_search_vector, websearch_to_tsquery('english', 'liability clause')) * 0.5) +
 ((1 - (embedding <=> '[0.012, -0.043, …]')) * 0.5) AS hybrid_score
FROM enterprise_documents
WHERE tenant_id = 'org_99412'
 AND status = 'ACTIVE'
ORDER BY hybrid_score DESC
LIMIT 10;

Das Wichtigste in Kürze

Vektordatenbanken verschwinden nicht. Vorbei ist nur die Gewohnheit, jeden Dokument-Chunk gedankenlos in einen In-Memory-HNSW-Index zu kippen. Vier Regeln für 2026:

  1. Setzen Sie bei Problemen mit exakten Treffern nicht allein auf Vektoren. Wenn Nutzer nach SKU, Namen oder Code-Syntax suchen, kombinieren Sie Vektoren von Anfang an mit BM25 oder einem invertierten Index.
  2. Behalten Sie die HNSW-Speicherrechnung im Blick. Ab etwa 10M Vektoren lohnt ein Blick auf festplattenbasierte Indizes wie DiskANN von Microsoft oder auf binäre Quantisierung, bevor die Kosten davonlaufen.
  3. Nutzen Sie Vektoren zum Routen, nicht zum Lesen. Statt winziger 200-Token-Chunks wählen Sie die drei bis fünf besten vollständigen Dokumente mit jeweils 50k Token oder mehr und geben sie an ein LLM mit langem Kontext.
  4. Konsolidieren Sie. Sofern Sie nicht bei mehreren Milliarden Vektoren mit SLAs unter 10 ms liegen, erledigt Ihre bestehende relationale Datenbank, etwa PostgreSQL mit pgvector, die Aufgabe wahrscheinlich und erspart Ihnen die Synchronisationsfehler eines verteilten Systems.