~/tools / Embeddingi i wyszukiwanie (RAG) / pgvector SQL Builder

pgvector SQL Builder — SQL dla pgvector: tabela, indeks HNSW/IVFFlat i zapytanie o sąsiadów

Napisz SQL do przechowywania i wyszukiwania embeddingów w PostgreSQL z pgvector: tabelę z kolumną vector(n) lub halfvec(n), indeks HNSW lub IVFFlat z klasą operatorów pasującą do wybranej odległości oraz zapytanie o najbliższych sąsiadów z czytelnym wynikiem. Narzędzie sprawdza ograniczenia podane w dokumentacji pgvector i szacuje, ile miejsca zajmują wektory. Nic nie opuszcza Twojej przeglądarki.

Każdy wektor zajmuje 1,544 bajtów, więc 10,000 wierszy zajmuje około 15.4 MB samych wektorów (bez indeksów i innych kolumn).

1. Rozszerzenie i tabela

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id bigserial PRIMARY KEY,
  content text NOT NULL,
  embedding vector(384) NOT NULL
);

2. Indeks

CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);

3. Wyszukiwanie

PREPARE przyjmuje wektor pytania z /api/embed jako $1. Przekaż go jako tekst, na przykład '[0.01,-0.02,…]'.

PREPARE search_documents(vector(384)) AS
  SELECT id, content, 1 - (embedding <=> $1) AS cosine_similarity
  FROM documents
  ORDER BY embedding <=> $1
  LIMIT 5;

-- EXECUTE search_documents('[0.0123, -0.0456, ...]');

Ograniczenia i wartości domyślne z README i kodu źródłowego pgvector 0.8.7, sprawdzone dnia 2026-11-04. pgvector README

Wszystko dzieje się w Twojej przeglądarce. Narzędzie pisze SQL i z niczym się nie łączy.

pgvector to rozszerzenie open source, które dodaje do PostgreSQL wyszukiwanie wektorów według podobieństwa, dzięki czemu embeddingi tworzone w Ollamie można przechowywać w tej samej bazie co pozostałe dane. Kilka szczegółów łatwo pomylić. Kolumna musi mieć tyle samo wymiarów co Twój model embeddingów. Każda odległość ma własny operator: <=> dla odległości cosinusowej, <-> dla odległości L2, <#> dla ujemnego iloczynu skalarnego i <+> dla odległości L1. Przybliżony indeks jest używany tylko wtedy, gdy zbudowano go z klasą operatorów dla tej samej odległości, na przykład vector_cosine_ops dla <=>, oraz gdy zapytanie sortuje według samego operatora w kolejności rosnącej i ma LIMIT. To narzędzie pisze trzy części z jednego zestawu wyborów: CREATE EXTENSION i CREATE TABLE, CREATE INDEX oraz polecenie PREPARE, które zwraca najbliższe wiersze z czytelnym wynikiem (podobieństwo cosinusowe to 1 minus odległość cosinusowa, a iloczyn skalarny to <#> pomnożone przez -1). Stosuje ograniczenia z README i kodu źródłowego pgvector w wersji 0.8.7: do 16,000 wymiarów w kolumnie, indeksy do 2,000 wymiarów dla vector i 4,000 dla halfvec, brak klasy operatorów L1 dla IVFFlat, w HNSW m od 2 do 100 oraz ef_construction od 4 do 1,000 i co najmniej 2 × m. W HNSW wyszukiwanie zwraca co najwyżej hnsw.ef_search wierszy (domyślnie 40), więc narzędzie ostrzega, gdy LIMIT jest większy. Dla IVFFlat uzupełnia lists i probes według punktów wyjścia z README: rows / 1000 dla do 1M wierszy, sqrt(rows) powyżej tego oraz sqrt(lists) dla probes. Wygenerowane SQL uruchomiono na pgvector 0.8.7 z PostgreSQL 16, używając prawdziwych wektorów o 384 wymiarach z Ollamy, a EXPLAIN pokazał użycie indeksu.

Główna logika tego narzędzia jest otwartoźródłowa, na licencji MIT. github.com/seigo5555/toolkitbox-lib/src/pgvector-sql.ts

Zastosowania

  • Utworzyć tabelę na fragmenty dokumentów, zanim wczytasz embeddingi z Ollamy do PostgreSQL
  • Sprawdzić, który operator pasuje do której klasy operatorów dla odległości cosinusowej, L2, iloczynu skalarnego lub L1, aby indeks był naprawdę używany
  • Oszacować, ile miejsca zajmują wektory na małym VPS, i porównać vector z halfvec

Jak używać

  1. Wpisz nazwę tabeli i liczbę wymiarów swojego modelu embeddingów. To długość jednego wektora z /api/embed; pokazuje ją Embedding Similarity Calculator na tej stronie.
  2. Wybierz typ, odległość i indeks. Dokumentacja Ollamy zaleca podobieństwo cosinusowe w większości zastosowań wyszukiwania semantycznego, a /api/embed zwraca wektory o długości 1.
  3. Skopiuj trzy bloki i uruchom je w psql lub innym kliencie. Indeks IVFFlat utwórz po wczytaniu danych; indeks HNSW można utworzyć na pustej tabeli.

FAQ

Którą odległość wybrać?

Dokumentacja embeddingów Ollamy zaleca podobieństwo cosinusowe w większości zastosowań wyszukiwania semantycznego. W pgvector <=> zwraca odległość cosinusową, a narzędzie zamienia ją na cosine_similarity jako 1 minus odległość. Dla wektorów o długości 1, takich jak te z /api/embed, odległość cosinusowa, odległość L2 i iloczyn skalarny ustawiają wiersze w tej samej kolejności, ponieważ dla takich wektorów kwadrat odległości L2 to 2 minus 2 razy podobieństwo cosinusowe.

HNSW czy IVFFlat?

README pgvector mówi, że HNSW ma lepszą wydajność zapytań niż IVFFlat (pod względem kompromisu między szybkością a recallem), ale buduje się wolniej i zużywa więcej pamięci oraz że można go utworzyć na pustej tabeli, bo nie ma etapu trenowania. IVFFlat buduje się szybciej, zużywa mniej pamięci i powinien być tworzony, gdy tabela zawiera już trochę danych. Bez indeksu pgvector wykonuje dokładne wyszukiwanie, które daje doskonały recall.

Dlaczego moje zapytanie nie używa indeksu?

README mówi, że zapytanie musi mieć ORDER BY i LIMIT, a ORDER BY musi być samym operatorem odległości w kolejności rosnącej, a nie wyrażeniem takim jak 1 - (embedding <=> …) DESC. Operator musi też pasować do klasy operatorów indeksu: <=> z vector_cosine_ops, <-> z vector_l2_ops, <#> z vector_ip_ops i <+> z vector_l1_ops. Narzędzie pisze jedno i drugie z tego samego wyboru. README zaznacza też, że skan całej tabeli może być szybszy, gdy tabela jest mała.

Dlaczego dostaję mniej wierszy niż LIMIT?

W HNSW wyniki są ograniczone przez hnsw.ef_search, domyślnie 40; gdy wypróbowaliśmy LIMIT 100 na tabeli z 200 wierszami, dostawaliśmy 40 wierszy, dopóki nie podnieśliśmy hnsw.ef_search do 100. README dodaje, że filtrowanie przez WHERE jest stosowane po przeskanowaniu indeksu, więc warunek może zostawić jeszcze mniej wierszy. Od wersji 0.8.0 iteracyjne skanowanie indeksu (SET hnsw.iterative_scan = strict_order lub relaxed_order) w razie potrzeby przeszukuje większą część indeksu.

Czym jest halfvec?

Typem wektora o połowicznej precyzji. Każdy wektor zajmuje 2 × wymiary + 8 bajtów zamiast 4 × wymiary + 8, a indeksy HNSW i IVFFlat na halfvec obsługują do 4,000 wymiarów zamiast 2,000. Każdy element jest liczbą zmiennoprzecinkową o połowicznej precyzji, więc wartości są przechowywane mniej dokładnie.

Czy moje dane są dokądś wysyłane?

Nie. Narzędzie tylko pisze SQL w Twojej przeglądarce i nigdy nie łączy się z bazą danych.

Powiązane artykuły

Powiązane