Warum die Suchgeschwindigkeit für KI-Agenten und Kontext-Engineering wichtig ist
Unsere Benchmarks auf einem 20-Millionen-Dokumentenkorpus zeigen, dass Elasticsearch bei der gefilterten Vektorsuche bis zu 8-mal mehr Durchsatz als OpenSearch liefert und gleichzeitig höhere Recall@100 in den getesteten Konfigurationen erzielt. Kontextgestaltung erfordert mehr als nur einen schnellen Vektorabruf. Teams benötigen außerdem starke Relevanzkontrollen, wie hybride Such- und Filterfunktionen, eine einfache Bedienung und eine vorhersehbare Leistung bei der Iteration von Workflows. Da die Agenten jedoch oft mehrmals pro Anfrage Abfrage-, Auswertungs- und erneute Abfrage-Schleifen durchlaufen, wirkt sich die Latenz bei der Datenabfrage multiplikativ aus, sodass Verbesserungen in diesem Bereich direkt zu einer besseren Reaktionsgeschwindigkeit über den gesamten Prozess hinweg und zu geringeren Kosten führen.

Graph 1: Durchsatz.
Für das Kontext-Engineering ist der Abruf kein einmaliger Schritt. Agenten und Anwendungen führen wiederholt Schleifen aus, wie z. B. Abrufen → Begründung → Abrufen, um Abfragen zu verfeinern, Fakten zu überprüfen, einen fundierten Kontext zusammenzustellen und Aufgaben zu erledigen. Dieses Muster ist typisch für agentenbasierte Workflows und iterative Retrieval Augmented Generation (RAG). Da der Abruf pro Nutzeranfrage mehrfach aufgerufen werden kann, verzögert sich die Reaktion und/oder erhöht die Infrastrukturkosten.

Abbildung 1: Kontext-Engineering verwandelt einen großen Kontextpool (Dokumente, Memory, Tools, Chatverlauf) durch wiederholte Abfrage und Kuratierung in ein begrenztes Kontextfenster eines Large Language Models (LLM).
Die optimale Implementierung des Kontext-Engineerings ist eine aufstrebende Technik. Die Iterationszahlen variieren stark je nach Workflow. Das Schlüsselkonzept, das für diese Benchmark-Ergebnisse am grundlegendsten ist, ist, dass das Kontext-Engineering richtungsabhängig ist: Iterative Abfragen machen Latenz zu einem Multiplikator.
Warum ist die Leistung der Vektorsuche so wichtig?
Stellen Sie sich vor, ein Verkäufer beantwortet die Frage: „Ich brauche einen Handgepäck-Rucksack unter 60 €, in den ein 15-Zoll-Laptop passt, der wasserabweisend ist und bis Freitag geliefert werden kann.“
In der Produktion gibt der Assistent nur selten eine Vektorabfrage aus und hält dann an. Es führt einen Abrufzyklus aus, um den richtigen Kontext aufzubauen, und jeder Schritt wird typischerweise durch Filter eingeschränkt, wie Verfügbarkeit, Region, Versandversprechen, Markenregeln und Richtlinienberechtigung.
Schritt 1: Absicht interpretieren und in Einschränkungen übersetzen.
Der Agent wandelt die Anfrage in strukturierte Filter und eine semantische Abfrage um, wie zum Beispiel:
- Filterkriterien: Auf Lager, lieferbar an die Postleitzahl des Nutzers, Lieferung bis Freitag, Preis unter 60 €, gültiges Angebot
- Vektorabfrage: „Bordrucksack für 15-Zoll-Laptop, wasserabweisend“
Schritt 2: Kandidaten abrufen und anschließend verfeinern.
Es wiederholt oft das Abrufen mit Variationen, um gute Übereinstimmungen nicht zu verpassen:
- „Reiserucksack in Kabinengröße mit Laptophülle“
- „wasserabweisender Pendlerrucksack 15 Zoll“
- „ leichtgewichtiger Kabinenrucksack “
Für jede Abfrage werden die gleichen Berechtigungsfilter verwendet, da das Abrufen irrelevanter oder nicht verfügbarer Elemente eine Verschwendung von Kontext darstellt.
Schritt 3: Erweitern, um Details zu bestätigen und das Risiko zu reduzieren.
Der Agent ruft dann erneut ab, um wichtige Attribute zu überprüfen, die die endgültige Antwort beeinflussen:
- Angaben zu Material und Wasserfestigkeit
- Abmessungen und Passform des Laptopfachs
- Rückgabebestimmungen oder Garantiebeschränkungen
- Alternative Optionen, wenn der Bestand gering ist
Dies ist mehrstufiges Kontext-Engineering: Abrufen, schlussfolgern, abrufen, zusammenstellen.
Warum Latenz und Recall für das Kontext-Engineering wichtig sind
Diese Interaktionen können Dutzende gefilterter Abrufaufrufe pro Nutzersitzung umfassen. Das macht die Latenz pro Anruf zu einem direkten Multiplikator der End-to-End-Reaktionszeit, und eine niedrige Rückrufrate erzwingt zusätzliche Wiederholungsversuche oder führt dazu, dass der Agent geeignete Elemente übersieht, was die Antwortqualität verschlechtert.
Fazit: In kontextbasierten Systemen ist die gefilterte approximative Suche nach nächsten Nachbarn (ANN) keine einfache Nachschlageoperation. Sie ist ein wiederholter Vorgang unter Einschränkungen, sodass die Leistung der Vektorsuche sofort in Latenz, Durchsatz und Kosten angezeigt wird, selbst wenn das Large Language Model (LLM) die sichtbarste Komponente ist.
Benchmarking
Ergebnisse
In Diagramm 2 stellt jeder Punkt eine Testkonfiguration dar. Die besten Ergebnisse werden oben links angezeigt, was eine höhere Erinnerungsrate bei geringerer Latenz bedeutet. Die Ergebnisse von Elasticsearch liegen durchweg näher am oberen linken Rand als die von OpenSearch, was auf eine höhere Geschwindigkeit und Genauigkeit bei gleicher Arbeitslast hinweist.

Diagramm 2: Treffer und durchschnittliche Latenz im Vergleich, Rescore von 1.
Einige wichtige Einblicke
s_n_r_value: Kurzschrift fürsize_numCandidates_rescoreOversample(k und numCandidates in diesen Tests gleich numCandidates gesetzt), zum Beispiel100_500_1bedeutet size=100, numCandidates=500 und k=500, rescore oversample=1- Erinnerung: Gemessener Recall@100 für diese Konfiguration
- Durchschnittslatenz (ms): Durchschnittliche End-to-End-Latenz pro Abfrage
- Durchsatz: Abfragen pro Sekunde
- Erinnerung %: Relative Verbesserung der Trefferquote von Elasticsearch gegenüber OpenSearch (Elasticsearch minus OpenSearch) / OpenSearch
- Latenz Xs: Die durchschnittliche Latenz von OpenSearch dividiert durch die durchschnittliche Latenz von Elasticsearch
- Durchsatz Xs: Elasticsearch-Durchsatz geteilt durch den OpenSearch-Durchsatz
| Engine | `s_n_r_value` | Abruf | Durchschnittliche Latenz (ms) | Durchsatz | Erinnerung % | Latenz Xs | Durchsatz Xs |
|---|---|---|---|---|---|---|---|
| Elasticsearch | 100_250_1 | 0,7704 | 25 | 534,75 | 9,70 % | 2,28 | 1,91 |
| OpenSearch | 100_250_1 | 0,7023 | 57,08 | 279,58 | |||
| Elasticsearch | 100_500_1 | 0,8577 | 25,42 | 524,14 | 7,20 % | 2,4 | 2 |
| OpenSearch | 100_500_1 | 0,8001 | 60,9 | 262,12 | |||
| Elasticsearch | 100_750_1 | 0,8947 | 29,67 | 528,09 | 5,72 % | 2,25 | 2,21 |
| OpenSearch | 100_750_1 | 0,8463 | 66,76 | 239,11 | |||
| Elasticsearch | 100_1000_1 | 0,9156 | 29,65 | 534,5 | 4,66 % | 2,46 | 2,44 |
| OpenSearch | 100_1000_1 | 0,8748 | 72,88 | 219,01 | |||
| Elasticsearch | 100_1500_1 | 0,9386 | 31,84 | 497,3 | 3,38 % | 2,71 | 2,68 |
| OpenSearch | 100_1500_1 | 0,9079 | 86,16 | 185,4 | |||
| Elasticsearch | 100_2000_1 | 0,9507 | 34,69 | 457,2 | 2,57 % | 2,98 | 2,96 |
| OpenSearch | 100_2000_1 | 0,9269 | 103,36 | 154,55 | |||
| Elasticsearch | 100_2500_1 | 0,9582 | 37,9 | 418,43 | 1,99 % | 3,28 | 3,26 |
| OpenSearch | 100_2500_1 | 0,9395 | 124,29 | 128,53 | |||
| Elasticsearch | 100_3000_1 | 0,9636 | 41,86 | 379,4 | 1,62 % | 3,46 | 3,44 |
| OpenSearch | 100_3000_1 | 0,9482 | 144,67 | 110,34 | |||
| Elasticsearch | 100_4000_1 | 0,9705 | 50,28 | 316,21 | 1,06 % | 3,87 | 3,85 |
| OpenSearch | 100_4000_1 | 0,9603 | 194,36 | 82,22 | |||
| Elasticsearch | 100_5000_1 | 0,9749 | 58,77 | 270,91 | 0,73 % | 4,43 | 4,41 |
| OpenSearch | 100_5000_1 | 0,9678 | 260,33 | 61,38 | |||
| Elasticsearch | 100_6000_1 | 0,9781 | 66,75 | 238,59 | 0,52 % | 4,91 | 4,89 |
| OpenSearch | 100_6000_1 | 0,973 | 327,44 | 48,81 | |||
| Elasticsearch | 100_7000_1 | 0,9804 | 74,64 | 213,49 | 0,38 % | 5,28 | 5,27 |
| OpenSearch | 100_7000_1 | 0,9767 | 394,24 | 40,53 | |||
| Elasticsearch | 100_8000_1 | 0,9823 | 82,28 | 193,59 | 0,27 % | 6,86 | 6,83 |
| OpenSearch | 100_8000_1 | 0,9797 | 564,14 | 28,33 | |||
| Elasticsearch | 100_9000_1 | 0,9837 | 90,08 | 176,96 | 0,16 % | 7,63 | 7,61 |
| OpenSearch | 100_9000_1 | 0,9821 | 687,25 | 23,25 | |||
| Elasticsearch | 100_10000_1 | 0,9848 | 97,64 | 163,31 | 0,08 % | 8,38 | 8,36 |
| OpenSearch | 100_10000_1 | 0,984 | 818,64 | 19,53 |
Zum Beispiel beträgt OpenSearch bei 100_9000_1 im Durchschnitt 687 Millisekunden pro Abruf gegenüber 90 Millisekunden bei Elasticsearch, und in einer 10-Schritte-Abrufschleife entspricht das etwa 10 × (687 - 90) = sechs Sekunden zusätzlicher Wartezeit.
Die vollständigen Ergebnisse ansehen.
Methodik
Wir verwendeten Python, um die Anfragen zu senden und die Antwortzeiten sowie weitere Statistiken zu verfolgen. Wir haben die folgenden Anfragen an die Engines gesendet. Bedenken Sie, dass die Leistungsfähigkeit jeder Vektorsuchmaschine davon abhängt, wie Sie ihre Kernparameter einstellen: wie viele Kandidaten berücksichtigt werden sollen, wie aggressiv die Neubewertung erfolgen soll und wie viel Kontext zurückgegeben werden soll. Diese Einstellungen wirken sich direkt sowohl auf die Trefferquote (die Wahrscheinlichkeit, die richtige Antwort zu finden) als auch auf die Latenz (wie schnell Sie Ergebnisse erzielen) aus.
In unseren Benchmarks verwendeten wir die gleichen Kandidaten-, Rescore- und Ergebnisgrößeneinstellungen, die man typischerweise in einer agentenbasierten Abrufschleife anpasst, und wir maßen, wie Elasticsearch unter dieser Arbeitslast abschneidet. Anschließend führten wir OpenSearch mit denselben Einstellungen als Referenz durch.
OpenSearch
"size": <RESULT_SIZE>: Anzahl der an den Client zurückgegebenen Treffer. In diesem Benchmark ist die Ergebnisgröße 100, um Recall@100 zu berechnen."k": <NUMBER_OF_CANDIDATES>: Die Anzahl der nächstgelegenen Nachbarkandidaten."ef_search": <NUMBER_OF_CANDIDATES>: Die Anzahl der zu untersuchenden Vektoren."oversample_factor": <OVERSAMPLE>: Wie viele Kandidatenvektoren werden abgerufen, bevor das Rescoring erfolgt.
Elasticsearch
"size": <RESULT_SIZE>: Anzahl der an den Client zurückgegebenen Treffer. In diesem Benchmark ist die Ergebnisgröße 100, um Recall@100 zu berechnen."k": <NUMBER_OF_CANDIDATES>: Anzahl der nächsten Nachbarn, die von jedem Shard zurückgegeben werden sollen."num_candidates": <NUMBER_OF_CANDIDATES>: Anzahl der zu berücksichtigenden nächsten Nachbarn pro Shard bei derknn-Suche."oversample": <OVERSAMPLE>: Wie viele Kandidatenvektoren werden abgerufen, bevor das Rescoring erfolgt.
Beispiel
Knn Die Abfrage (100_500_1) würde wie folgt lauten:
OpenSearch
Elasticsearch
Die vollständige Konfiguration, zusammen mit Terraform-Skripten, Kubernetes-Manifesten und dem Benchmarking-Code, ist in diesem Repository im Ordner es-9.3-vs-os-3.5-vector-search verfügbar.
Cluster-Einrichtung
Wir führten unsere Tests auf sechs e2-Standard-16-Cloud-Servern durch, jeder mit 16 vCPUs und 64 GB RAM. Auf jedem Server haben wir 15 vCPUs und 56 GB RAM jedem Kubernetes-Pod zugewiesen, der den Suchmaschinen-Node ausführt, wobei 28 GB für den JVM-Heap reserviert waren.
Die Cluster liefen mit Elasticsearch 9.3.0 und OpenSearch 3.5.0 (Lucene 10.3.2). Da beide Systeme in diesem Benchmark die gleiche Lucene-Version verwenden, können die beobachteten Unterschiede im Durchsatz und in der Latenz nicht allein Lucene zugeschrieben werden, sondern spiegeln vielmehr Unterschiede in der Art und Weise wider, wie die einzelnen Engines die gefilterte k-nächste-Nachbarn-Suche (kNN) und das Rescoring integrieren und ausführen. Wir haben einen einzelnen Index mit drei Primäre Shards und einem Replikat verwendet (also insgesamt 6 Shards, einer pro Node).
Wir verwendeten außerdem einen separaten Server in derselben Region, um den Benchmark-Client auszuführen und Zeitstatistiken zu erfassen.

Abbildung 2: Diagramm des Clusteraufbaus.
Der Datensatz
Für diesen Benchmark verwendeten wir einen umfangreichen Katalog-Embedding-Datensatz im E-Commerce-Stil mit 20 Millionen Dokumenten, der die reale gefilterte Vektorsuche in großem Umfang widerspiegeln soll.
Jedes Dokument stellt einen Katalogartikel dar und beinhaltet:
- Eine 128-dimensionale Dichtevektoreinbettung, die für das ungefähre kNN-Abrufverfahren verwendet wird.
- Strukturierte Metadatenfelder, die zur Filterung verwendet werden (zum Beispiel die Gültigkeit und Verfügbarkeit von Artikeln sowie andere Katalogbeschränkungen), die das gemeinsame Produktionsmuster ermöglichen, die nächstgelegenen Nachbarn abzurufen, jedoch nur innerhalb einer zulässigen Teilmenge.
Wir haben diesen Datensatz gewählt, weil er die Kernleistungsherausforderung widerspiegelt, die wir bei agentenbasierten und RAG-Systemen im Produktiveinsatz beobachten: Vektorähnlichkeit allein reicht nicht aus, die Suche wird häufig durch Filter eingeschränkt, und das System muss unter diesen Einschränkungen eine hohe Trefferquote bei gleichzeitig niedriger Latenz pflegen. Im Vergleich zu kleineren QA-Datensätzen spiegelt ein Korpus von 20 Millionen Dokumenten auch besser den Umfang und den Kandidatendruck wider, denen gefilterte ANN-Systeme in der Praxis ausgesetzt sind.
Fazit
In modernen KI-Architekturen, insbesondere solchen, die auf Kontext-Engineering aufbauen, ist die Geschwindigkeit der Vektorsuche kein unbedeutendes Implementierungsdetail. Sie ist ein Multiplikator. Wenn Agenten und Workflows durch Abrufen → Verarbeiten → Abrufen iterieren, beeinflusst die Abrufleistung direkt die End-to-End-Latenz, den Durchsatz und die Qualität des in das Modell eingespeisten Kontexts.
In unseren Benchmarks lieferte Elasticsearch konstant einen höheren Abruf bei geringerer Latenz als OpenSearch in Szenarien, in denen die Korrektheit vom Abruf des richtigen Dokuments und nicht nur eines ähnlichen Vektors abhängt. An einem kontrollierten Datensatz ist der Unterschied deutlich, und in der Produktion akkumulieren sich diese Gewinne über große Volumina von Abrufaufrufen, wodurch die Reaktionsfähigkeit verbessert, der Kapazitätsspielraum erhöht und die Infrastrukturkosten reduziert werden.




