PRODSuwerenna europejska platforma BaaSOtwórz Panel →

Natywna sztuczna inteligencja · 9 min odczytu

Indeks HNSW w Postgres: dobrze indeksuj do wyszukiwania wektorowego

Affane Daylami · Fondateur · 6 kwietnia 2026

Powrót do bloga

HNSW to algorytm indeksowania zalecany przez pgvector do wyszukiwania wektorów podobieństwa w Postgres. W tym przewodniku pokazano, jak utworzyć odpowiednio dostrojony indeks HNSW. Liczą się trzy możliwości: typ kolumny w zależności od rozmiaru osadzonych elementów, parametry m i ef_construction podczas budowy oraz ef_search przy każdym żądaniu w celu ustalenia przypomnienia i opóźnienia.

Ten tekst w języku angielskim został wygenerowany automatycznie na podstawie francuskiego oryginału i nie był jeszcze recenzowany.
Ta strona została przetłumaczona automatycznie. Wersja angielska jest miarodajna.

Natywne wyszukiwanie wektorów w Aurabase (RAG, pgvector, osadzanie) opiera się na tym samym mechanizmie indeksowania, opisanym szczegółowo na stronie Native AI na stronie Postgres. W tym przewodniku założono tabelę Postgres z już zainstalowanym pgvectorem, kolumną typu vectori co najmniej kilkoma tysiącami wierszy. Poniżej proste skanowanie sekwencyjne jest często szybsze niż przybliżony indeks.

Najważniejsze

  • HNSW nie wymaga żadnej fazy szkoleniowej, w przeciwieństwie do IVFFlat: indeks zbudowany jest na wstawkach, dostępnych w pgvector od wersji 0.5.0.
  • Dwa parametry określają jakość indeksu podczas konstruowania: m (połączenia na węzeł, domyślnie 16) i ef_construction (szerokość wyszukiwania podczas konstruowania, domyślnie 64).
  • Trzeci parametr, hnsw.ef_search (domyślnie pgvector: 40), jest dostosowywany dla każdego żądania bez przebudowy indeksu, aby rozstrzygnąć przywołanie i opóźnienie.
  • pgvector caps Indeksowanie HNSW typu vector do 2000 wymiarów. Poza tym (na przykład osadzenie z 3072 wymiarami) do indeksowania konieczne jest rzutowanie na halfvec.
  • pgvector 0.8.6 to wersja osadzona w obrazie dzierżawcy Aurabase Postgres, zweryfikowana bezpośrednio w pliku Dockerfile 24 sierpnia 2026 r.
#
Zrozumieć

Co to jest indeks HNSW w pgvector?

HNSW oznacza Hierarchiczny Żeglowny Mały Świat. Jest to indeks grafowy: każdy wektor staje się węzłem połączonym z najbliższymi sąsiadami, zorganizowanymi w kilku nałożonych na siebie warstwach. Wyszukiwanie rozpoczyna się od góry wykresu, w najrzadszej warstwie, a następnie przechodzi w dół, warstwa po warstwie, do najbardziej odpowiednich sąsiadów. Czas wyszukiwania staje się zatem prawie logarytmiczny, a nie liniowy w zależności od liczby linii.

IVFFlat, drugi indeks pgvector, działa inaczej: dzieli przestrzeń wektorową na listy określone w trakcie szkolenia na istniejącej próbce, zanim będzie można cokolwiek zaindeksować. HNSW nie ma tego ograniczenia, każde wstawienie bezpośrednio wzbogaca wykres, co ułatwia operowanie na tabeli, która stale rośnie. Z drugiej strony indeks HNSW zużywa więcej pamięci i jego zbudowanie zajmuje więcej czasu niż równoważny indeks IVFFlat na tym samym woluminie.

pgvector wprowadza obsługę HNSW w wersji 0.5.0. Późniejsze wersje dodają przydatne funkcje do tego przewodnika: typ halfvec (0.7.0) do indeksowania ponad 2000 wymiarów oraz parametr hnsw.iterative_scan (0.8.0) do poprawy przypominania filtrowanych zapytań. Jeśli przed podjęciem decyzji porównasz pgvector z dedykowaną bazą wektorów, nasze porównanie pgvector z Pinecone, Weaviate i Qdrant szczegółowo opisuje kompromisy.

#
Krok 1

Przed utworzeniem indeksu sprawdź swoją wersję pgvector

Najpierw potwierdź zainstalowaną wersję pgvector. Rozszerzenie, które jest zbyt stare, powoduje, że niektóre funkcje tego przewodnika po cichu nie działają, szczególnie halfvec i hnsw.iterative_scan.

psqlsql
SELECT extversion FROM pg_extension WHERE extname = 'vector';

HNSW istnieje od wersji pgvector 0.5.0. Typ halfvecniezbędny do indeksowania osadzania powyżej 2000 wymiarów wymaga wersji co najmniej 0.7.0. Parametr hnsw.iterative_scan żąda wersji 0.8.0.

W projektach Aurabase pytanie nie pojawia się: obraz Postgres osadza pgvector 0.8.6, zarówno we współdzielonym klastrze Postgres (docker/Postgres.Dockerfile, zbudowany bezpośrednio na pgvector/pgvector:0.8.6-pg16-bookworm), jak i w 16 instancjach CNPG Postgres dedykowanych dla każdego projektu (docker/Postgres.CNPG.Dockerfile, który dziedziczy pgvector 0.8.6 z oficjalny obraz CloudNativePG). Zweryfikowano w obu plikach Dockerfile 24 sierpnia 2026 r.

#
Krok 2

Wybierz odpowiedni typ kolumny w zależności od rozmiaru osadzonych elementów

Typ kolumny zależy od rozmiaru osadzonych elementów, a nie tylko od modelu, który je generuje. pgvector przechowuje w pamięci klasyczny wektor typu vectorz ograniczeniem do 16 000 wymiarów. Ale indeksowanie HNSW tego typu jest ograniczone do 2000 wymiarów: poza tym CREATE INDEX kończy się niepowodzeniem.

Typowe modele osadzania często przekraczają ten próg: text-embedding-3-large z OpenAI lub gemini-embedding-2 z Google natywnie generują do 3072 wymiarów. Aby zindeksować te wektory za pomocą HNSW, rzuć kolumnę na halfvec (precyzja przechowywania zmniejszona o połowę), co przesuwa limit indeksowania znacznie poza 2000 wymiarów.

WymiaryKolumnaHNSW na wektorzeWymaga odlewania
768osadzanie_768TakNIE
1536osadzanie_1536TakNIE
3072osadzanie_3072Nie (> 2000 przyciemnień)Tak, obsada::halfvec(3072)

Silnik Aurabase RAG ilustruje ten kompromis w produkcji: obsługiwane są trzy klasy wymiarów (768, 1536, 3072), przechowywane w trzech odrębnych kolumnach tej samej tabeli embeddings. Kolumny 768 i 1536 są indeksowane bezpośrednio w HNSW na typie vector. Kolumna 3072 jest indeksowana za pomocą rzutowania ::halfvec(3072), dokładnie w celu obejścia ograniczenia wymiaru 2000.

migration.sqlsql
CREATE INDEX idx_embeddings_vec_768 ON embeddings
  USING hnsw (embedding_768 vector_cosine_ops)
  WHERE embedding_768 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_1536 ON embeddings
  USING hnsw (embedding_1536 vector_cosine_ops)
  WHERE embedding_1536 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_3072 ON embeddings
  USING hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  WHERE embedding_3072 IS NOT NULL;

Aby uzyskać szczegółowe informacje na temat pozyskiwania (porcjowanie, wywoływanie dostawcy osadzania, wstawianie), zobacz samouczek potoku RAG na pgvector.

#
Krok 3

Utwórz indeks z parametrami m i ef_construction

Minimalna składnia jest wystarczająca dla pierwszego indeksu, z domyślnymi wartościami pgvector.

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops);

pgvector następnie stosuje m = 16 i ef_construction = 64. Aby jawnie dostosować te wartości, użyj klauzuli WITH:

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 24, ef_construction = 100);
Przyspiesz dużą budowę

Przed zbudowaniem indeksu HNSW na dużym stole tymczasowo zwiększ maintenance_work_mem dla sesji: jest to, zgodnie z samą dokumentacją pgvector, najbardziej bezpośrednią dźwignią skracającą czas budowy.

Co zmienia parametr m?

m ustawia maksymalną liczbę połączeń utrzymywanych przez każdy węzeł na wykresie w każdej warstwie. Wyższa wartość zagęszcza wykres: wzrasta przywoływanie, ale zużycie pamięci i czas konstrukcji również rosną, w przybliżeniu liniowo. Wartość domyślna (16) jest odpowiednia w większości przypadków. Zwiększenie liczby do 24 lub 32 jest szczególnie uzasadnione w przypadku dużych osadów, gdzie rozróżnienie między bliskimi i odległymi sąsiadami staje się dokładniejsze.

Co zmienia ef_construction?

ef_construction ustawia rozmiar listy kandydatów badanej podczas konstruowania indeksu dla każdego wstawionego węzła. Wyższa wartość poprawia jakość końcowego wykresu, a tym samym potencjalne wycofanie, kosztem dłuższego czasu konstrukcji. W przeciwieństwie do m, ten parametr nie ma żadnych kosztów w momencie zapytania: jest to jednorazowa inwestycja, płacona tylko raz w momencie utworzenia indeksu.

Częściowe indeksy dla kilku klas wymiarów w tej samej tabeli

Gdy tabela przechowuje wiele kolumn wektorowych (po jednej na klasę wymiaru, tak jak robi to Aurabase), indeksuj każdą kolumnę osobno za pomocą klauzuli WHERE colonne IS NOT NULL. Ten częściowy indeks pozwala uniknąć indeksowania pustych linii dla klas, które nie są używane w danej linii, co zmniejsza rozmiar indeksu i przyspiesza jego budowę, nie ponosząc żadnych kosztów przywołania.

Wybór klasy operatora (vector_cosine_ops, vector_l2_ops lub vector_ip_ops) musi odpowiadać metryce, na podstawie której uczono modelu osadzania. Najnowsze modele osadzania tekstu są szkolone pod kątem podobieństwa cosinus: vector_cosine_ops (lub halfvec_cosine_ops w kolumnie rzutowanej) jest zatem najbezpieczniejszym wyborem domyślnym.

#
Krok 4

Ustaw ef_search w czasie zapytania

Wartość ef_search jest ustawiana przy każdym zapytaniu, a nie podczas budowania indeksu. Określa rozmiar listy kandydatów sprawdzanych podczas wyszukiwania: im jest ona większa, tym lepsze przypominanie, kosztem dłuższego opóźnienia. pgvector ustawia wartość domyślną na 40.

psqlsql
SET LOCAL hnsw.ef_search = 100;

SELECT id, content
FROM embeddings
ORDER BY embedding <=> '[...]'::vector
LIMIT 10;

Wartość 40 rzadko wystarcza, gdy tylko zapytanie łączy wyszukiwanie wektorowe z filtrem WHERE zastosowanym po przeskanowaniu indeksu (w przestrzeni nazw, dzierżawie lub innym kryterium metadanych). Skan HNSW przywraca surowych kandydatów ef_search, a następnie filtr odrzuca ich część. Jeśli zbyt mało kandydatów przeżyje, ostateczny LIMIT okaże się niedopełniony.

Dlatego silnik Aurabase RAG rozszerza ef_search dynamicznie zgodnie z żądanym top_k, zamiast utrzymywać stałą wartość 40: ef = max(top_k × 4, 64). Do wyszukiwania 5 najbliższych wyników używa się ef_search = 64; wyszukiwanie 50 najpopularniejszych zastosowań ef_search = 200. Tę formułę można dostosować do zmiennej środowiskowej w przypadku wdrożeń, które wymagają innego kompromisu w zakresie przypominania/opóźnienia.

pgvector 0.8 dodaje drugą dźwignię dla tego samego problemu: hnsw.iterative_scan. W trybie strict_order lub relaxed_orderwyszukiwanie stopniowo rozszerza swoje wyszukiwanie, aż po przefiltrowaniu zgromadzi wystarczającą liczbę wyników, zamiast zatrzymywać się na ustalonej liście kandydatów. Aurabase aktywuje go domyślnie w strict_order, ale chroni połączenie w punkcie zapisu. W wersji pgvector wcześniejszej niż 0.8, gdzie ten parametr nie istnieje, zapytanie jest kontynuowane w trybie pogorszonym, a nie kończy się niepowodzeniem.

#
Idź dalej

Zbuduj kompletny rurociąg RAG

Ten indeks HNSW to tylko jeden element kompletnego potoku RAG: fragmentacja, generowanie osadzania, przetwarzanie, a następnie wyszukiwanie. Nasz samouczek krok po kroku buduje ten potok od początku do końca na pgvector, od pierwszego wstawienia do zapytania o podobieństwo. Dokumentacja techniczna zawiera również szczegółowe informacje na temat wszystkich natywnych możliwości sztucznej inteligencji Aurabase zbudowanych na Postgres.

#
Często zadawane pytania

Często zadawane pytania

HNSW czy IVFFlat: który wybrać z pgvector?+
HNSW nadaje się do większości przypadków wyszukiwania wektorowego w środowisku produkcyjnym: lepsze przywołanie przy równym opóźnieniu, brak wcześniejszej fazy szkolenia i dobra tolerancja na tabele, które stale rosną. IVFFlat pozostaje istotny, gdy dostępna pamięć jest bardzo ograniczona, kosztem ogólnie mniejszej liczby przywoływań i niezbędnego ponownego szkolenia, jeśli dystrybucja danych zmienia się znacząco.
Ile pamięci zaplanować dla indeksu HNSW?+
Rząd wielkości zależy bezpośrednio od m i liczby indeksowanych wektorów: każdy węzeł przechowuje do m połączeń na warstwę, oprócz samego wektora. Aby wiarygodnie oszacować rzeczywisty wolumen, zbuduj indeks na reprezentatywnym podzbiorze danych. Następnie zmierz jego rozmiar za pomocą pg_relation_size(), zamiast polegać na niezmierzonej zasadzie.
Czy za pomocą HNSW możemy indeksować osadzania zawierające ponad 2000 wymiarów?+
Nie bezpośrednio na typie wektorowym: pgvector odmawia zbudowania indeksu HNSW przekraczającego 2000 wymiarów dla tego typu. Rozwiązaniem jest rzutowanie kolumny na halfvec w czasie tworzenia indeksu, co przesuwa limit indeksowania poprzez zmniejszenie o połowę precyzji przechowywania. Jest to dokładnie podejście stosowane w produkcji 3072-wymiarowej klasy osadzania Aurabase.

GOTOWY DO WDROŻENIA?

Twój backend w pięć minut.

Karta kredytowa nie jest wymagana · 500 MB za darmo · 50 000 MAU