Porównanie pięciu wbudowanych systemów przechowywania wektorów: FAISS, Chroma, LanceDB, VectLite
Pięć wbudowanych baz danych wektorowych przetestowanych pod kątem lokalnego RAG: FAISS, Chroma, LanceDB, VectLite i NumPy porównano pod względem dokładności, opóźnienia, filtrów oraz problemu początkowego uruchomienia.
Źródła: I Benchmarked 5 Vector Databases for a Local RAG. Only One Actually Surprised Me.
Większość porównań „najlepszych baz danych wektorowych” przypomina tylko przeredagowane strony startowe samych dostawców: Pinecone jest szybkie, Qdrant solidne, Chroma proste – wszyscy wygrywają. Ten tekst wychodzi od węższego zakresu potrzeb. Żadnego klastra, żadnego Dockera, żadnych otwartych portów, żadnego planu zarządzanego. Tylko wbudowana baza wektorowa składająca się z jednego lokalnego pliku, poleceń pip install oraz trzech linijek kodu w Pythonie. Oto więc domowy test wydajności pięciu silników przeznaczonych dokładnie do tego zastosowania.
Liczby
Zbiór danych zawierał 5 000 wektorów o 384 wymiarach, które były wyszukiwane 50 razy za pomocą podobieństwa kosinowego. Wszystko działało na macOS (x86_64) z Pythonem 3.12.8, przy użyciu domyślnych ustawień każdego silnika.
| Silnik | Przyjmowanie danych (vec/s) | Szukanie p95 | Recall@10 | Filtrowanie p95 | Recall@10 przy filtrowaniu |
|---|---|---|---|---|---|
| FAISS | 743,099 | 0,65 ms | 1,000 | n/d | brak filtrowania |
| NumPy exact | 2,412,231 | 2,59 ms | 1,000 | 9,25 ms | 1,000 |
| Chroma | 2,011 | 3,14 ms | 0,840 | 18,76 ms | 1,000 |
| VectLite 0,10.0 | 154 | 5,71 ms | 0,966 | 10,28 ms | 0,966 |
| LanceDB | 20,120 | 12,20 ms | 1,000 | 14,11 ms | 1,000 |
W ciągu dziesięciu sekund: FAISS jest najszybszy, chociaż ledwo można go uznać za bazę danych. Chroma jest najłatwiejszy do wprowadzenia, ale jego domyślne wskaźniki odzyskiwania danych na poziomie 84% stanowią problem, który wielu ludzi ignoruje. VectLite osiąga 96,6% wskaźnika odzyskiwania danych w trybie wbudowanym bez konieczności dostosowań, co było niespodzianką. LanceDB dąży do perfekcyjnego odzyskiwania danych, ale kosztem opóźnienia. NumPy pełni rolę sędziego, a nie uczestnika konkursu.
Dlaczego „najszybszy” to błędna metryka rankingu
Rynek baz danych wektorowych to pole bitwy marketingowej. Każdy dostawca publikuje wyniki testów, w których przypadkowo wygrywa, artykuły porównawcze powtarzają te liczby bez kontekstu, a wszyscy skupiają się na opóźnieniach. Samo opóźnienie może wprowadzać w błąd. Odpowiedź w pół milisekundy przy niewłaściwych wynikach jest gorsza niż 5 ms potrzebne na uzyskanie prawidłowych wyników. To właśnie mierzy wskaźnik召回, i dlatego poważne zestawy takie jak ANN-Benchmarks (https://ann-benchmarks.com/) przedstawiają召回 w zależności od przepustowości.
Dlatego ten test mierzy obie rzeczy jednocześnie: z jednej strony opóźnienia p50, p95 i p99 oraz liczba zapytań na sekundę, a z drugiej召回@10 w porównaniu z dokładnym wyszukiwaniem kosinusowym przy użyciu zwykłego NumPy.
Co zostało, a co nie zostało przetestowane
Projekt to niewielki pakiet w Pythonie, vectlite-benchmark-lab. Każdy silnik implementuje wspólną interfejs VectorStore, a narzędzie testowe wywołuje je po kolei. Obejmuje ono:
- Przyjmowanie danych partiami
- Wyszukiwanie k-NN z pomiarem dokładności
- Filtrowanie metadanych opartych na dokładnym dopasowaniu według
tenant_id - Czas rozruchu
- Tworzenie kopii zapasowych i przenośność
- Eksport do plików CSV, JSON oraz wykresów w Matplotlib
A to, co pomija, zostaje podane od razu: brak konfiguracji rozproszonej lub wielo węzłowej, maksymalnie 5 000 wektorów w tym etapie, brak jakiejkolwiek optymalizacji indeksu oraz brak użycia Qdrant czy pgvector, ponieważ wymagają one działającego serwera, a celem było czyste działanie lokalne. Ten ostatni wybór jest celowy. Pierwsze istotne pytanie nie brzmi, kto wygra po dwóch tygodniach optymalizacji, lecz jak zachowuje się silnik po jego zainstalowaniu bez żadnych zmian.
Metoda
Prawdą podstawową jest prosta wyszukiwanka kosinusa w NumPy. Stopień odnalezienia silnika to udział prawdziwych sąsiadów, które zwraca, obliczony średnio na podstawie wszystkich zapytań. Konfiguracja wykonywania:
vectlite : 0.10.0
vectors : 5,000 (synthetic, normalized)
dimensions : 384
queries : 50
top_k : 10
metric : cosine
filter : tenant_id (exact-match)
warmup : 5 queries discarded
hardware : macOS x86_64, Python 3.12.8
Aby odtworzyć to na swoim komputerze, uruchom pełny polecenie:
PYTHONPATH=src python -m vectlite_benchmark_lab run \
--stores vectlite,faiss,chroma,lancedb,numpy_exact \
--vectors 5000 --dimensions 384 --queries 50 \
--top-k 10 --batch-size 500 \
--output-dir results/vectlite-0.10.0 \
--data-dir data/vectlite-0.10.0
Następnie porównaj swoje wyniki z tymi i przyjrzyj się różnicom.
FAISS: górna granica szybkości
FAISS wygrywa we wszystkich kolumnach dotyczących opóźnienia: 0,65 ms p95 przy doskonałym odzyskiwaniu danych, co jest mniej więcej tym, czego można oczekiwać od biblioteki napisanej w C++, optymalizowanej specjalnie pod ten cel od dekady. Jednak nie jest to baza danych – nie posiada wbudowanego filtrowania metadanych, brakuje mu funkcji trwałego przechowywania danych oraz możliwości tworzenia przenośnych kopii zapasowych. Można ją otoczyć warstwą, która te funkcje dodaje, i faktycznie tak się robi, ale „out of the box” jest bardziej podobna do biblioteki matematycznej niż do narzędzia przeznaczonego do dostarczania klientom. Porównywanie jej z Chromą to jak porównywanie silnika F1 z Toyotą: jeden jest szybszy na torze, drugi dowozi zakupy do domu. Pozostaje ona w tabeli jako odniesienie. Jeśli potrzebujesz tylko surowego wyszukiwania wektorowego, to oczywisty wybór.
Chroma: łatwy start, uważaj na odzyskiwanie danych
Chroma jest standardem dla prototypów RAG, a doświadczenie programisty uzasadnia to wybór. Zainstaluj chromadb, napisz pięć linijek kodu i dokumenty zostaną zindeksowane.
Problemem jest precyzja wyszukiwania. Bez żadnych filtrów Chroma znajduje jedynie 84% prawdziwych wyników, co oznacza, że około jeden z sześciu oczekiwanych rezultatów w ogóle się nie pojawia. To akceptowalne dla prototypu. W produkcji, gdzie jakość wyszukiwania wpływa na odpowiedź modelu, stanowi to ukrytą stratę istotności, której API nie ujawnia. Dostosowanie ustawień HNSW pomaga zrekompensować tę różnicę, o ile wiemy, że jest to konieczne. Przy użyciu filtrów precyzja wynosi 100%, ale opóźnienie p95 wzrasta do 18,76 ms, co jest znacznie wolniej niż w pozostałych przypadkach przy tym samym zadaniu. Werdykt: doskonałe od pierwszego dnia i nadal dobre po trzydziestu dniach, pod warunkiem dostosowania przed wdrożeniem w produkcję.
VectLite: niespodzianka
Wersja 0.10.0 osiąga 96,6% precyzji przy ustawieniach domyślnych, co jest najwyższym wynikiem wśród wszystkich dostępnych silników. Czas wyszukiwania w trybie prostym wynosi 5,71 ms, co plasuje go pośrodku grupy (Chroma 3,14, LanceDB 12,20). Przy zadaniu z filtrowaniem czas ten wynosi 10,28 ms, podczas gdy w przypadku Chromy to 18,76 ms, więc jest tam prawie dwa razy szybszy.
Widać postępy od najwcześniejszych wersji. W porównaniu z v0,1.x szybkość przetwarzania wzrosła z 47 do 154 wektorów na sekundę (około 3,3 raza szybciej), precyzja wzrosła z 0,948 do 0,966, a czas przetwarzania z filtrowaniem spadł z 18,6 ms do 10,3 ms, co stanowi spadek o 45%.
Słabym punktem jest szybkość przetwarzania. 154 wektory na sekundę to powolne tempo w porównaniu z 2000 i więcej wektorów na sekundę u Chromy, a także bardzo wolne w porównaniu z LanceDB. Przy kilku tysiącach indeksowanych dokumentów to nie ma znaczenia. Jednak przy milionie wektorów oznacza to długie czekanie, więc prawdopodobnie to następna rzecz, którą trzeba poprawić. Mimo to był to jedyny silnik w grupie, którego wyniki nie wymagały żadnych usprawiedliwień.
LanceDB: perfekcyjna dokładność, wolniejsze wyszukiwanie
LanceDB osiąga 100% dokładności i przetwarza 20 120 wektorów na sekundę, co na papierze wygląda imponująco. Kosztem jest opóźnienie wyszukiwania: 12,20 ms p95, co czyni go najwolniejszym z pięciu. Dla procesowania tysięcy zapytań w ciągu nocy w trybie partii to nie ma znaczenia. Dla narzędzia interaktywnego, w którym ktoś czeka przy klawiaturze, to ma duży wpływ na szybkość działania. Dobry do zadań partii i analiz, ale nieco wolny do użycia interaktywnego.
NumPy: sędzia
Wyszukiwanie kosinusowe metodą siłowej na całej macierzy gwarantuje z definicji perfekcyjną dokładność, przy akceptowalnym opóźnieniu do kilkudziesięciu tysięcy wektorów, po czym szybko spada. To nie jest produkt – to arbiter, według którego oceniane są pozostałe silniki.
Który wybrać
Testy nie wyłaniają zwycięzcy – pokazują jedynie kompromisy. Oryginalne dopasowanie według przypadków użycia:
- Szybki prototyp RAG: Chroma, dzięki dwuminutowej konfiguracji i dużemu ekosystemowi
- Pamięć AI wbudowana: VectLite, oferująca najlepszą domyślną zdolność odzyskiwania danych oraz plik przenośny
- Lokalna ścieżka przetwarzania partii: LanceDB, zapewniająca doskonałe odzyskiwanie danych i szybkie ich przetwarzanie
- Czysta sieć neuronowa bez filtrowania: FAISS, charakteryzująca się niezrównaną opóźnieniem
- Produkcja rozproszona: Qdrant lub Milvus – kategoria inna, nieprzetestowana tutaj
Start początkowy i zapasowe kopie
Dwie miary, których większość testów pomija. Start uruchomienia, czyli czas ponownego otwarcia bazy danych po restartie: FAISS potrzebuje 0,001 ms, LanceDB 2 ms, Chroma 5 ms, a VectLite 3 059 ms. VectLite bardzo drogo płaci pod względem czasu ponownego otwarcia. Nie ma to znaczenia dla procesu działającego przez długi czas, ale dla funkcji bez serwera lub narzędzia CLI uruchamianego na żądanie trzysekundowy start początkowy jest poważnym problemem i najprawdopodobniej pierwszą rzeczą do naprawy.
Zapasowa kopia: VectLite tworzy przenośny plik o rozmiarze 19 MB w ciągu 54 ms. Kopiowanie, tworzenie wersji i wdrażanie to zwykłe operacje z plikami. To właśnie ta cecha „wbudowania” rozwiązania sprawia, że jest ono skuteczne, to samo co utrzymało SQLite przy życiu przez dwa dekady.
Ograniczenia tego testu
Każdy test wydajności wymaga określenia ograniczeń. Tutaj jest ich pięć:
- 5 000 wektorów to mała liczba, a zachowanie systemu zmienia się już przy 100 tys. i więcej.
- Użyto wyłącznie domyślnych ustawień, a parametry Chromy i VectLite z dużym prawdopodobieństwem można dostosować do wyższych wartości.
- W testie nie wzięły udziału żadne silniki serwerowe: Qdrant, Milvus, Weaviate i pgvector zostały pominięte.
- Był to jeden test, bez przedziałów ufności i bez powtórzeń.
- Test przeprowadzono na jednym komputerze, więc inne urządzenia mogą dać inne wyniki.
Kod jest otwarty, a wyniki powtarzalne, więc wykryty błąd lub stronniczość zasługują na zgłoszenie.
Kolejne kroki i wnioski
To test stanowi punkt wyjścia, a nie ostateczną ocenę. Krótka lista na następny etap: wektor o długości 100k, test o 768 wymiarach przeprowadzony we wszystkich silnikach; test w stylu RAG wykorzystujący korpusy w formacie Markdown i PDF z zapytaniami napisanymi przez ludzi; dostosowana dokładność przywracania informacji, aby silniki konkurowały przy porównywalnej precyzji; szybszy start chłodny dla VectLite; oraz powtarzane testy z przedziałami ufności.
Pościg za „najlepszą bazą danych wektorowych” kończy się bez uniwersalnej odpowiedzi, ponieważ zależy od tego, jak oceniasz stosunek dokładności do opóźnienia, szybkości wprowadzania danych oraz czasu uruchomienia. Nie wyróżnił się żaden wyraźny lider, lecz każdy silnik ma swoją specyfikę. FAISS to punkt odniesienia pod względem szybkości, udający bazę danych. Chroma to prosty w użyciu narzędzie, które wymaga dostosowań przed wprowadzeniem do produkcji. LanceDB to perfekcjonista, który nie ma nic przeciwko wolniejszej pracy. NumPy to bezstronny sędzia, który nie potrafi się skalować. VectLite to rozwiązanie, które cicho osiąga wymagany poziom dokładności bez żadnych kompromisów.
Dla lokalnego agenta, narzędzia CLI lub systemu RAG działającego offline na laptopie, VectLite stanowi przekonującą alternatywę: SQLite uczynił lokalne dane relacyjne nudnymi i trudnymi do przenoszenia, a VectLite dąży do pełnienia tej samej roli przy użyciu pamięci AI. Oznacza to plik o wielkości 19 MB, który odpowiada w około 6 ms.
Linki referencyjne: ANN-Benchmarks pod adresem https://ann-benchmarks.com/, notatki dotyczące benchmarków Qdrant pod adresem https://qdrant.tech/benchmarks/, FAISS pod adresem https://github.com/facebookresearch/faiss, dokumentacja Chroma pod adresem https://docs.trychroma.com/ oraz LanceDB pod adresem https://lancedb.github.io/lancedb/.