Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds
Powrót do kolekcji
Przewodnik10 min czytania

Elasticsearch, wyszukiwanie wektorowe i pełnotekstowe

Elasticsearch łączy wyszukiwanie pełnotekstowe z wektorowym. Wersja 9.4, DiskBBQ, pole semantic_text, licencje AGPL i ELv2 oraz porównanie z Milvus.

Elasticsearch, wyszukiwanie wektorowe i pełnotekstowe

Elasticsearch to rozproszona wyszukiwarka, która od kilku wydań traktuje wektory na równi z tekstem. Oznacza to, że jeden system obsługuje dopasowanie po słowach kluczowych i podobieństwo semantyczne, bez utrzymywania dwóch osobnych baz i bez ręcznego łączenia wyników. Bieżąca wersja to 9.5.0 z 4 sierpnia 2026 roku, a projekt jest dostępny na potrójnej licencji, w tym otwartej AGPLv3.

Kiedy Elasticsearch jest sensownym wyborem na wektory

Postawię tezę, która porządkuje resztę tekstu: jeśli w Twoim systemie już działa Elasticsearch, dokładanie osobnej bazy wektorowej rzadko się opłaca. Jeśli nie działa, stawianie go wyłącznie dla wektorów opłaca się jeszcze rzadziej.

Powód leży w tym, czym ta wyszukiwarka jest z natury. To silnik odwróconego indeksu z całą warstwą, której dedykowane bazy wektorowe nie mają: analizatorami językowymi, tokenizacją, obsługą synonimów, agregacjami, podświetlaniem fragmentów, uprawnieniami na poziomie dokumentu. Jeśli produkt potrzebuje tych rzeczy, dostajesz je razem z wektorami, a to zwykle przeważa nad różnicą w czystej wydajności wyszukiwania przybliżonego.

Odwrotnie wygląda to przy zastosowaniu czysto wektorowym. Utrzymanie klastra Elasticsearcha wymaga wiedzy o sterowaniu pamięcią maszyny wirtualnej Javy, o odłamkach i o replikach. Jeśli jedyne, czego potrzebujesz, to szukanie najbliższych sąsiadów dla dwóch milionów wektorów, Qdrant albo Milvus postawisz szybciej i utrzymasz mniejszym nakładem.

Jest też trzeci przypadek, w którym decyzja jest oczywista. Kiedy zapytania użytkowników mieszają obie intencje, na przykład „faktura marzec 2025 od dostawcy energii", żaden z tych systemów samodzielnie nie odpowie dobrze. Potrzebujesz dopasowania dokładnego na numerach i dat oraz semantycznego na reszcie. Elasticsearch robi to w jednym zapytaniu i to jest jego najmocniejszy argument.

semantic_text, czyli najkrótsza droga do wyszukiwania semantycznego

Klasyczna ścieżka wektorowa wygląda tak: wybierasz model osadzeń, dzielisz tekst na fragmenty, liczysz wektory, zapisujesz je razem z metadanymi, przy zapytaniu liczysz wektor pytania i szukasz. Pięć kroków, z których każdy można zepsuć.

Pole semantic_text skraca to do jednego. Deklarujesz typ pola, a wyszukiwarka sama dobiera reprezentację wektorową, sama dzieli długi tekst na fragmenty i sama liczy osadzenia przy indeksowaniu.

Code
JSON
PUT /dokumenty
{
  "mappings": {
    "properties": {
      "tresc": { "type": "semantic_text" }
    }
  }
}

Zapytanie jest równie krótkie i przyjmuje zwykły tekst, nie wektor:

Code
JSON
GET /dokumenty/_search
{
  "query": {
    "semantic": {
      "field": "tresc",
      "query": "jak rozliczyć fakturę korygującą"
    }
  }
}

W wersji 9.4 domyślne ustawienia tego pola zmieniły się w trzech miejscach naraz i warto o tym wiedzieć, jeśli porównujesz wyniki między środowiskami. Domyślnym modelem jest teraz jina-v5, domyślną precyzją BFLOAT16, a domyślnym typem indeksu disk_bbq. Indeks utworzony przed aktualizacją zachowa stare ustawienia, więc dwa środowiska na tej samej wersji potrafią zwracać nieco inne uszeregowanie, jeśli jedno powstało wcześniej.

Wygoda ma tu swoją cenę i uczciwie jest ją nazwać. Oddajesz kontrolę nad doborem modelu i nad sposobem dzielenia tekstu. Przy dokumentach o nietypowej strukturze, na przykład tabelach albo kodzie, własne dzielenie fragmentów zwykle daje lepsze wyniki niż automatyczne. Zacznij od semantic_text, a przejdź na ręczną konfigurację dopiero wtedy, gdy pomiary pokażą, że warto.

Kwantyzacja i DiskBBQ

Wektory zajmują dużo pamięci i to jest główny koszt tej części systemu. Tysiąc wymiarów w liczbach zmiennoprzecinkowych pojedynczej precyzji to cztery kilobajty na dokument, czyli cztery gigabajty na milion dokumentów, zanim doliczysz indeks.

Kwantyzacja polega na zapisaniu tych liczb z mniejszą precyzją. Elastic rozwija własny wariant tej techniki pod nazwą BBQ, a materiały producenta mówią o kompresji do 32 razy i ograniczeniu zużycia pamięci o około 95 procent przy zachowaniu trafności. To liczby marketingowe, więc traktuj je jako rząd wielkości, a nie jako obietnicę dla Twoich danych. Sam mechanizm jest jednak realny i przy większych zbiorach to on decyduje o rozmiarze klastra.

Wersja 9.4 przyniosła tu dwie konkretne zmiany. DiskBBQ, czyli wariant trzymający strukturę na dysku, jest teraz domyślny dla nowo tworzonych indeksów, a jego algorytm przepisano tak, że przy bardzo wąskich filtrach wyszukiwanie działa trzy razy szybciej albo lepiej. Doszła też możliwość wyboru precyzji: 1, 2, 4 albo 7 bitów na wymiar.

Ten wybór jest miejscem, w którym warto zainwestować godzinę pomiarów. Jeden bit daje największą oszczędność i najniższą wierność, siedem bitów odwrotnie. Reguła, która sprawdza się w praktyce: zacznij od domyślnych ustawień, zmierz trafność na własnym zestawie zapytań z oczekiwanymi wynikami, i dopiero przy niezadowalającym wyniku podnoś precyzję. Podnoszenie jej profilaktycznie to płacenie za pamięć, której nie potrzebujesz.

Wyszukiwanie hybrydowe i łączenie rang

Samo podobieństwo wektorowe zawodzi tam, gdzie liczy się dokładny ciąg znaków. Numer faktury, nazwisko, sygnatura sprawy, nazwa modelu urządzenia. Model osadzeń widzi je jako podobne do innych numerów i nazwisk, co daje wyniki poprawne semantycznie i bezużyteczne praktycznie.

Rozwiązaniem jest połączenie obu podejść. Prostszy wariant to zwykłe zapytanie logiczne, w którym część dopasowująca słowa i część semantyczna trafiają do klauzuli should, każda z własnym wzmocnieniem. Wadą jest to, że wyniki obu części mają różne skale, więc dobieranie wzmocnień staje się zgadywanką.

Lepiej działa łączenie rang metodą odwrotności pozycji. Zamiast porównywać wyniki punktowe, bierze ona pod uwagę wyłącznie miejsce dokumentu na każdej z list, dzięki czemu skale przestają mieć znaczenie.

Code
JSON
GET /dokumenty/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        { "standard": { "query": { "match": { "tresc": "faktura korygująca" } } } },
        { "standard": { "query": { "semantic": { "field": "tresc", "query": "jak rozliczyć fakturę korygującą" } } } }
      ],
      "rank_window_size": 50,
      "rank_constant": 20
    }
  }
}

Dwa parametry z tego zapytania warto rozumieć. rank_window_size mówi, ile wyników brać z każdej listy przed połączeniem, i zwiększanie go poprawia szansę na znalezienie dokumentu widocznego tylko w jednej z nich, kosztem czasu odpowiedzi. rank_constant tłumi przewagę pierwszych pozycji, więc jego podniesienie sprawia, że dokument dziesiąty na obu listach wygrywa z dokumentem pierwszym na jednej i nieobecnym na drugiej.

Licencje, największe źródło nieporozumień

Ten temat generuje więcej zamieszania niż cała reszta i wraca w każdej dyskusji o wyborze wyszukiwarki, więc warto go rozłożyć na części.

W styczniu 2021 roku projekt przestał być wydawany na licencji Apache 2.0 i przeszedł na dwie licencje niezatwierdzone przez Open Source Initiative. To wtedy Amazon utworzył odgałęzienie o nazwie OpenSearch. W sierpniu 2024 roku Elastic dołożył trzecią opcję, AGPLv3, która jest licencją otwartą w rozumieniu OSI, więc dzisiejszy stan to potrójne licencjonowanie: AGPLv3, Elastic License 2.0 oraz SSPL, z wyborem po stronie użytkownika.

Praktyczne znaczenie tych różnic sprowadza się do jednego pytania: czy zamierzasz oferować Elasticsearcha jako usługę zarządzaną innym firmom. Jeśli nie, a to sytuacja niemal każdego zespołu produktowego, wszystkie trzy licencje pozwalają Ci robić to, co chcesz, łącznie z użyciem komercyjnym i wewnętrznym hostowaniem. Elastic License 2.0 zabrania właśnie odsprzedawania jako usługi, SSPL wymaga otwarcia całego stosu takiej usługi, a AGPLv3 nakłada obowiązek publikacji modyfikacji.

Osobną warstwą jest podział funkcji na poziomy subskrypcji. Darmowy poziom Basic obejmuje wyszukiwanie wektorowe, hybrydowe, pole semantic_text i całą podstawową funkcjonalność. Płatne poziomy dokładają rzeczy z obszaru bezpieczeństwa i zarządzania, na przykład uprawnienia na poziomie pola i wiersza, uwierzytelnianie jednokrotne czy uczenie maszynowe do wykrywania anomalii. Przy planowaniu wdrożenia to właśnie ten podział, a nie licencja kodu, częściej okazuje się rozstrzygający.

Elasticsearch a dedykowane bazy wektorowe

CechaElasticsearchMilvusQdrantpgvector
Wyszukiwanie pełnotekstowepełne, z analizatoramipodstawowe, rzadkie wektorypodstawoweprzez rozszerzenie
Wyszukiwanie wektorowetak, z kwantyzacjątak, główny celtak, główny celtak, prostsze
Agregacje i raportowaniemocneograniczoneograniczonepełny SQL
Próg wejścia operacyjnegowysokiwysokiniskiżaden przy istniejącej bazie
LicencjaAGPLv3, ELv2, SSPLApache 2.0Apache 2.0PostgreSQL
Zużycie pamięciwysokie, maszyna Javyśrednieniskiezależne od bazy

Zestawienie warto czytać przez pryzmat tego, co już masz. Przy istniejącej bazie PostgreSQL i zbiorze poniżej miliona wektorów rozszerzenie pgvector rozwiązuje sprawę w jeden wieczór i nie dokłada żadnego nowego elementu do utrzymania. Przy potrzebie prawdziwego wyszukiwania tekstowego z odmianą wyrazów, synonimami i podświetlaniem żadna z dedykowanych baz wektorowych nie dorówna Elasticsearchowi, bo to nie jest ich zadanie.

Koszty i zasoby

Rachunek za Elasticsearcha rzadko wynika z liczby dokumentów, a prawie zawsze z pamięci. Warto rozumieć trzy jej rodzaje, bo mylenie ich prowadzi do klastrów źle zwymiarowanych w obie strony.

Sterta maszyny wirtualnej Javy obsługuje struktury zapytań i pamięć podręczną. Zalecenie mówi, żeby nie przekraczać połowy dostępnej pamięci maszyny i nie wychodzić powyżej około trzydziestu gigabajtów, bo powyżej tego progu maszyna wirtualna przestaje używać skompresowanych wskaźników i efektywnie traci pamięć zamiast zyskiwać.

Druga połowa pamięci należy do systemu operacyjnego i to ona utrzymuje w pamięci podręcznej pliki indeksu. Przy wyszukiwaniu wektorowym jest to krytyczne: jeśli struktura grafu nie mieści się w tej pamięci, każde zapytanie schodzi na dysk i opóźnienie rośnie o rząd wielkości. Warianty dyskowe, w tym DiskBBQ, są odpowiedzią właśnie na tę sytuację i pozwalają świadomie zaakceptować wolniejszy dostęp w zamian za mniejszą maszynę.

Trzeci element to miejsce na dysku, najtańsze z całej trójki i najczęściej przewymiarowane, podczas gdy pamięć bywa oszczędzana. Przy planowaniu klastra policz najpierw rozmiar wektorów po kwantyzacji, potem dodaj indeks odwrócony i metadane, a dopiero na końcu zastanawiaj się nad dyskiem.

Typowe błędy

Pierwszy to zmiana odwzorowania pola w istniejącym indeksie. Typów pól nie da się zmienić w miejscu, więc każda korekta oznacza utworzenie nowego indeksu i przeindeksowanie danych. Projekty, które tego nie przewidziały, odkrywają to w najgorszym momencie, czyli przy pierwszej poważnej zmianie modelu danych. Aliasy indeksów istnieją właśnie po to, żeby taka podmiana była niewidoczna dla aplikacji, i warto ich używać od pierwszego dnia.

Drugi to mieszanie modeli osadzeń. Wektory z dwóch różnych modeli nie są porównywalne, nawet przy tej samej liczbie wymiarów. Zmiana modelu wymaga przeliczenia całego zbioru, a nie tylko nowych dokumentów, bo inaczej stare i nowe rekordy przestają ze sobą konkurować sensownie.

Trzeci to zbyt dużo odłamków. Domyślne przekonanie, że więcej odłamków oznacza lepszą wydajność, jest odwrotnością prawdy dla małych zbiorów. Każdy odłamek to osobny indeks Lucene z własnym narzutem, więc dziesięć odłamków dla stu tysięcy dokumentów spowalnia zapytania zamiast je przyspieszać.

Czwarty dotyczy odświeżania. Dokument zapisany nie jest natychmiast widoczny w wynikach, bo indeks odświeża się co sekundę. Test integracyjny, który zapisuje i od razu szuka, będzie migotał. Do testów służy wymuszone odświeżenie, do produkcji cierpliwość, bo wymuszanie go przy każdym zapisie potrafi położyć klaster.

Piąty to głębokie stronicowanie. Przejście na stronę tysięczną przez parametr przesunięcia zmusza każdy węzeł do posortowania ogromnego zbioru. Do przewijania długich list służy przewijanie po wartościach sortowania, a nie zwiększanie przesunięcia.

FAQ

Czy Elasticsearch jest darmowy?

Kod jest dostępny na potrójnej licencji, w tym otwartej AGPLv3, i można go używać komercyjnie bez opłat. Darmowy poziom Basic obejmuje wyszukiwanie wektorowe i hybrydowe. Płatne subskrypcje dokładają głównie funkcje bezpieczeństwa i zarządzania, na przykład uprawnienia na poziomie pola.

Czym Elasticsearch różni się od OpenSearch?

OpenSearch to odgałęzienie utworzone przez Amazon w 2021 roku, po zmianie licencji Elasticsearcha, i od tego czasu oba projekty rozeszły się funkcjonalnie. Nowsze mechanizmy wektorowe, w tym pole semantic_text i wariant DiskBBQ, powstały po rozejściu i nie mają bezpośrednich odpowiedników.

Czy potrzebuję osobnej bazy wektorowej obok Elasticsearcha?

Zwykle nie. Jeśli klaster już działa i obsługuje Twoje dane, dokładanie drugiego systemu oznacza dwie ścieżki zapisu i konieczność utrzymania ich w zgodzie. Osobna baza ma sens dopiero przy skali, przy której koszt pamięci klastra przewyższa koszt utrzymania dodatkowego elementu.

Który sposób wyszukiwania hybrydowego wybrać?

Łączenie rang metodą odwrotności pozycji, o ile nie masz powodu, żeby ręcznie sterować wagami. Nie wymaga strojenia wzmocnień, bo ignoruje wyniki punktowe i patrzy wyłącznie na pozycje, co usuwa problem nieporównywalnych skal między dopasowaniem tekstowym a semantycznym.

Ile pamięci potrzebuje klaster z wektorami?

Zależy od precyzji zapisu. Bez kwantyzacji licz cztery kilobajty na tysiącwymiarowy wektor, czyli około czterech gigabajtów na milion dokumentów, plus narzut indeksu. Kwantyzacja tnie tę liczbę wielokrotnie, a wariant dyskowy pozwala zejść jeszcze niżej kosztem czasu odpowiedzi.

Szczegóły wydań opisują notatki wydawnicze Elasticsearcha, a stan licencjonowania wyjaśnia oficjalne FAQ o licencjach.