Vector search benchmark zeigt enorme Unterschiede bei den Erstellungszeiten
Ein vector search benchmark mit sechs Datenbank-Engines ergab, dass es zwischen 1,9 Minuten und 6,7 Stunden dauerte, dieselben 990.000 embeddings in einen abfragbaren Index umzuwandeln. Percona führte die Tests auf einem einzigen Rechner mit demselben Abfragesatz und derselben Container-Konfiguration durch und maß Erstellungszeit, Speicherplatz, Arbeitsspeicher, Genauigkeit, Durchsatz, gleichzeitig aktive Clients, gefilterte Suchvorgänge und die Auswirkungen des Neuschreibens von 10 % der Daten.
Der Korpus war dbpedia-openai-1000k-angular und enthielt 990.000 OpenAI embeddings, die jeweils durch 1.536 float32-Zahlen dargestellt wurden. Ein embedding ist eine numerische Darstellung, mit der Bedeutung oder Ähnlichkeit verglichen werden. Jede Engine verwendete HNSW, also Hierarchical Navigable Small World, eine Graphstruktur, die die Suche nach nahegelegenen Vektoren beschleunigt; M war auf 16 und die Ergebnisanzahl k auf 10 festgelegt. Der Host verfügte über einen Intel Xeon Gold 6230, 80 logische CPUs, AVX-512 und 187,5 GiB RAM. Der Datenbank-Container erhielt die CPUs 0 bis 63 und ein Speicherlimit von 120,8 GB; ein separater Test-Container erhielt 16 CPUs und 8 GB. Durch diese Trennung wurde verhindert, dass der von NumPy im Speicher gehaltene Abfragesatz dem Datenbankspeicher zugerechnet wurde.
Die getesteten Systeme waren die relationale Open-Source-Datenbank 11.8.8 mit MHNSW, dieselbe relationale Open-Source-Datenbank 12.3.2 mit MHNSW, AliSQL 8.0.44-2 mit VIDX, pgvector 0.8.6 auf der von vielen Webanwendungen genutzten relationalen Datenbank, Valkey 9.1.1 mit valkey-search sowie Percona Search for MongoDB 1.70.3-1 auf PSMDB 8.3.8-2. Percona Search war eine Technical Preview, die laut Dokumentation nicht für den Produktionseinsatz vorgesehen war. Bei den Tests wurde ein durch scalar quantization komprimierter Index verwendet, der numerische Werte mit geringerer Genauigkeit speichert, um Rechen- und Speicheranforderungen zu reduzieren.
Die Build-Performance unterschied sich drastisch. Percona Search war nach 1,9 Minuten abfragbar, Valkey nach 4,3 Minuten und die relationale Datenbank mit pgvector nach 40,9 Minuten. Die relationale Datenbank benötigte 26,9 Minuten für das Laden über COPY und 14 Minuten für den Aufbau des Index mit acht Workern. Die Open-Source-Datenbank 11.8 benötigte 3,6 Stunden, die Open-Source-Datenbank 12.3 benötigte 5,4 Stunden und AliSQL benötigte 6,7 Stunden. MHNSW und VIDX aktualisieren ihren Graph bei jedem INSERT, sodass das Laden und die Indexerstellung einen einzigen Vorgang bildeten. Ihre Raten lagen zwischen 41 und 76 Zeilen pro Sekunde, verglichen mit 613 bei pgvector und 30.170 bei Valkey.
Die Systeme mit der langsamsten Erstellung erzeugten die kleinsten Indizes. Die Open-Source-Datenbank und AliSQL verwendeten jeweils 3,9 GiB, da ihre Graphen mit 16 Bit quantisierte Vektorkopien enthielten, während pgvector und Valkey vollständige float32-Werte indexierten. Allein die Rohvektoren belegten 5,7 GiB. Die Indexgrößen betrugen 7,6 GiB bei pgvector, 11,3 GiB bei Valkey und 15,1 GiB bei Percona Search. Einschließlich der Tabellen belegte AliSQL 14,4 GiB, pgvector 15,2 GiB, die Open-Source-Datenbank 11.8 und Valkey jeweils 18,2 GiB und Percona Search 20,9 GiB. Der Index von Percona Search wurde später zu Beginn des churn-Tests mit 7,2 GiB gemessen, und Percona konnte nicht feststellen, welcher Wert den stabilen Zustand repräsentierte.
Der maximale residente Speicherverbrauch reichte von 14,3 GiB bei Valkey bis 48,8 GiB bei Percona Search. Die Cache-Zuweisungen waren Engine-spezifisch und nicht identisch: Die InnoDB-Systeme erhielten einen Buffer Pool von 42,3 GB und einen Graph-Cache von 30,2 GB, pgvector erhielt 72,5 GB shared_buffers sowie 12,1 GB maintenance_work_mem und Valkey verfügte über 108,7 GB maxmemory. Percona Search verwendete den standardmäßigen WiredTiger-Cache von MongoDB mit 57 bis 64 GB. Die Indexerstellung wurde auf acht Threads begrenzt, weil eine höhere Anzahl zu Ressourcenkonflikten führte und Schreibvorgänge in bereits gefüllte Indizes zum Stillstand bringen konnte.
Die Genauigkeit wurde als recall gemessen, also danach, wie viele der korrekten nearest neighbours die Suche zurückgab. Mit einem Client und einem recall von mindestens 0,99 erreichte die Open-Source-Datenbank 12.3 277 queries per second (QPS), Valkey 264, pgvector 210, AliSQL 126 und die Open-Source-Datenbank 11.8 lediglich 46. Der quantisierte Index von Percona Search erreichte höchstens einen recall von 0,892 und erfüllte die Anforderung daher nicht; ohne Quantisierung wurden beim Mindestwert von 0,99 88 QPS gemessen. Der Unterschied von 13 QPS zwischen der Open-Source-Datenbank 12.3 und Valkey war zu gering, um ihn anhand eines einzelnen Durchlaufs von Messrauschen unterscheiden zu können. Die Open-Source-Datenbank 12.3 wurde außerdem mit -march=native kompiliert, anders als die für die Open-Source-Datenbank 11.8, AliSQL und pgvector verwendeten x86-64-v3-Builds.
AliSQL zeigte eine ungeklärte Anomalie. Bei einem M von 16 stieg der Durchsatz von 2,6 auf 4,4 QPS, als ef_search, also der bei der Abfrage eingesetzte Suchaufwand, von 400 auf 800 erhöht wurde, obwohl mehr Arbeit denselben Index nicht schneller machen sollte. Die Median-Latenz sprang ebenfalls von 6,6 Millisekunden bei ef_search 80 auf 50,8 Millisekunden bei 120 und danach auf 191 bis 384 Millisekunden. Percona kennzeichnete diesen Bereich als unzuverlässig, statt ihn als gültiges Ergebnis zu behandeln.
Auch die Ergebnisse zur concurrency müssen sorgfältig interpretiert werden. Bei 32 Clients und ef_search 100 erreichte Valkey 5.683 QPS mit einer p99 latency von 10,2 Millisekunden, was bedeutet, dass 99 % der Abfragen innerhalb dieser Zeit abgeschlossen wurden. Pgvector erreichte 4.798 QPS bei 10,8 Millisekunden, während Percona Search 1.844 QPS bei 43,5 Millisekunden erreichte. Pgvector erzielte das 21,7-Fache seines Durchsatzes mit einem einzelnen Client. Das Testsystem verfügte jedoch nur über 16 CPUs, sodass das Abflachen der Ergebnisse von Valkey und Percona Search zwischen 16 und 32 Clients auf clientseitige CPU-Grenzen zurückzuführen sein könnte.
Für die Open-Source-Datenbank 11.8, die Open-Source-Datenbank 12.3 und AliSQL wurden keine Werte mit mehreren Clients gemeldet. Ihre Python-Clients mit Threads, die alle den Connector für die Open-Source-Datenbank verwendeten, blieben auch bei steigender Clientanzahl bei ungefähr einer gleichzeitig laufenden Abfrage. Percona hatte den genauen Mechanismus nicht ermittelt und kein Profiling der Server durchgeführt, weshalb das Unternehmen keine Aussage über deren serverseitige Skalierung traf. Das Testsystem wurde inzwischen so geändert, dass jeder Client in einem eigenen Betriebssystemprozess läuft. Diese Überarbeitung war jedoch nur mit synthetischen Treibern getestet worden und hatte diese Engines noch nicht erneut vermessen.
Filtering machte erhebliche Verhaltensunterschiede sichtbar. Bei 1 % selectivity, was bedeutet, dass nur 1 % der Zeilen die Bedingung erfüllten, erreichte Valkey einen recall von 0,9996 bei 8,2 QPS. Die Open-Source-Datenbank 12.3, die Open-Source-Datenbank 11.8 und AliSQL suchten nach dem Filtering weiter und hielten den recall zwischen 0,9724 und 0,9884, fielen jedoch auf weniger als ein QPS zurück; ihre p99 latency lag bei 10 bis 13 Sekunden. Percona Search filterte vor der vector search und beschleunigte sich von 71,9 QPS bei 10 % selectivity auf 117,5 QPS bei 1 %, wobei scalar quantization den recall jedoch auf 0,8666 begrenzte.
Das Standardverhalten von pgvector bestand darin, zuerst zu suchen, danach Zeilen zu entfernen, welche die Bedingung nicht erfüllten, und anschließend den Vorgang zu beenden. Bei 1 % selectivity gaben alle 500 Abfragen weniger als die angeforderten zehn Zeilen zurück. Daraus ergab sich ein recall von 0,1034 bei 237,1 QPS, ohne dass ein Fehler oder eine Warnung ausgegeben wurde. Pgvector 0.8 enthält iterative scan, um diesen Fall zu behandeln, doch der Benchmark testete diese Funktion nicht. Die praktische Erkenntnis lautet, dass ein schneller Abschluss nutzlos ist, wenn eine Anwendung unbemerkt unvollständige Ergebnisse erhält.
Nachdem 99.000 Zeilen gelöscht und erneut eingefügt worden waren, blieb pgvector mit 245 QPS stabil, ein Anstieg um 0,4 %, während Valkey um 4 % auf 460 QPS fiel. Percona Search sank um 38,9 % auf 113 QPS, obwohl sich der recall nur geringfügig von 0,8432 auf 0,8416 veränderte.