Eszközök/RAG és keresés
pgvector, értékelés: az a vektordatázis, amelyet nem kell üzemeltetned
Értékelés a pgvector 0.8.7-ről: iteratív indexszkennelés szűrt kereséshez, HNSW és IVFFlat, bináris kvantizálás 100 millió vektornál, és a CVE, amely az indexépítést javítási tétellé tette.
- Típus
- Vector database extension
- Ár
- PostgreSQL licence
Balázs Csorba··10 perc olvasás
- Vector search
- Postgres
- HNSW
- RAG
- Quantisation

A lényeg röviden
- A pgvector a PostgreSQL licenc alatt álló bővítmény, így a vektorok sima táblákban laknak, az ügyfélszűrők, JOIN-ek és kaszkádos törlések pedig tranzakciók maradnak.
- Az iteratív indexszkennelés, ami 0.8.0 óta létezik, a szűrt keresés megoldása: nélküle a sorok 10%-át eltaláló szűrő alapértelmezett ef_search 40 mellett körülbelül négy sort ad vissza.
- A AWS 367 GB-os HNSW-indexet mért 100 millió 768 dimenziós vektornál, szemben egy 38 GB-os, binárisan kvantizált indexszel, amely 1,1 óra alatt épült meg 16,1 helyett.
- A CVE-2026-3172, amelyet 2026 februárjában a 0.8.2 javított, puffer-túlcsordulás volt a párhuzamos HNSW-indexépítésben, amely más relációk adatait szivárogtathatta ki; a javításhoz nem kell újraindexelés.
- A korlát a memória, nem az API: ha az index nem fér már a shared_buffers-be, a válaszok a halfvec, a bináris kvantizálás, a particionálás vagy egy második rendszer.
A pgvector egy PostgreSQL-bővítmény, amely vektorokat egy sima tárolóba tesz, és SQL-lel keres azokban. Nem egy rácsavarozott lekérdezésnyelvű vektordatbázis: négy oszloptípust, hat távolságoperátort és két indextípust ad ahhoz a adatbázishoz, amelyet a legtöbb csapat amúgy is üzemeltet, a PostgreSQL licenc alatt, amely a lehető legmegengedőbb. Az itt képviselt álláspont: ez a helyes alapértelmezés szinte minden, legfeljebb néhány tízmillió vektorig terjedő előkeresési feladathoz, és aki ekkora méretnél külön vektordatázist épít, nem képességet vesz, hanem üzemeltetési terhet.
A Qdranttal, a Weavitate-val, a Chromával és a teljesen felhőben üzemeltetett vektor szolgáltatásokkal versengez, valamint minden olyan hosztolt Postgresszel, amely ma már alapból szállítja a bővítményt. Ami megszűnik, az egy teljes infrastruktúra-kategória: nincs második szolgáltatás, nincs második kommunikációs protokoll hitelesítésre, nincs második mentési ütemezés, nincs eltérés a sorok és azokat leíró beágyazások között. Ami megmarad, az a Postgres minden korlátja: egy csomópont memóriája, egy csomópont vacuumja, egy csomópont írási teljesítménye. És ezek válnak a tervezési paraméterekké abban a pillanatban, amikor az index már nem fér a RAM-ba.
Mi ez
Az első kiadás, a 0.1.0, 2021. április 20-án jelent meg, a jelenlegi kiadás pedig a 2026. október 1-i 0.8.7; a repository ellenőrzéskor 23.300 csillagot és 1.300 forkot mutatott. A PostgreSQL 13 és újabb verzióit támogatja, Docker-imageként, PGXN-en, APT-n, Yumon, Homebrew-en és conda-forge-on át kapható, és egyre több hosztolt szolgáltatónál előre telepítve érkezik. Ez azért számít, mert a régi verzión ragadt felhős szolgáltatás a leggyakoribb oka annak, hogy egy csapat úgy hiszi, megvan egy biztonsági javítása, ami nincs meg.
- Licenc: a PostgreSQL licenc, ugyanaz a megengedő szöveg, amelyet maga a PostgreSQL használ. Nincs open core, nincs kereskedelmi szint, nincs fizetős terv mögé rejtett funkció.
- A 0.8.7-es kiadás 2026. október 1-jén; a 0.8-as széria iteratív indexszkennelést ad 2024 októbere, a 0.8.0 óta, és ez a funkció tette kiszámíthatóvá a szűrt keresést.
- Négy típus:
vectordimenciónként 4 bájttal,halfvec2-vel,bitdimenciónként egy bittel, éssparsevecritka vektorokhoz legfeljebb 1000 nem-nulla elemmel. - Két indextípus: HNSW a legjobb sebesség-találati arányért, edzési lépés nélkül, IVFFlat gyorsabb építéshez és kisebb memóriaigényhez.
- Hat operátor, közvetlenül az ORDER BY-ban: L2 (
<->), belső szorzat (<#>), koszinusz (<=>), L1 (<+>), Hamming (<~>) és Jaccard (<%>). - A tárolás és a hozzáférés magától a Postgrestől jön: ACID, WAL-alapú replikáció, pillanatnyi visszaállítás, JOIN-ek és soronkénti biztonság ugyanabban a táblában, mint a beágyazások.
Hogyan működik
Index nélkül a vektor-lekérdezés szekvenciális szkennelés, távolságfüggvényre rendezett ORDER BY-jal: pontos eredmény, tökéletes találati arány, és a tábla méretével növekvő költség. Ezt a játszmát egy közelítő index megváltoztatja. A HNSW többrétegű grágot épít a vektorok fölé, és azon jár kicsit gyengébb találati arányért cserébe, a költség viszont többé nem nő a táblával; az IVFFlat vektorokat listákba rendez, és csak egy részüket vizsgálja. A mindent eldöntő részlet, hogy a lekérdezéstervező csak akkor nyúl az indexhez, ha a lekérdezés így néz ki: ORDER BY embedding <=> $1 LIMIT n. Ugyanez ORDER BY 1 - (embedding <=> $1) DESC alakban a README szerint nem használ indexet.
A második részlet, hogy hol fut a WHERE feltétel. A közelítő index jelölteket állít elő, a szűrő pedig csak utána fut rajtuk, így a szelektivitás és a találati arány összefonódik: az alapértelmezett hnsw.ef_search 40-es értékénél és egy a sorok 10%-át eltaláló feltétnél körülbelül négy sor jön vissza. Semmi nem hibás, az index egyszerűen sosem látta az ejtett sorokat. Ez a viselkedés a leggyakoribb oka annak, hogy valaki kevesebb találatot jelez vissza, és erre létezik dokumentált megoldás, nem pedig kerülőút.
Szűrt keresés
A szűrés itt nem utólagos gondolat, hanem elsőrendű probléma, és a dokumentáció négy lépést vesz végig abban a sorrendben, amelyben egy áttekintő kipróbálná őket. Hogy melyik érvényes, attól függ, mennyire szelektív a szűrő, mennyi találati arányra van valójában szükség, és hány különböző értéket vesz fel a szűrő: egy 50.000 értékes ügyfél-azonosító máshogy viselkedik, mint egy nyolc értékes országkód.
- Először a szűrő oszlopára sima B-tree index kerüljön. Ha a feltétel a sorok kis hányadát éri el, ez pontos legközelebbi szomszédokat ad közelítő index érintése nélkül, és a README épp ezt nevezi kiindulópontnak.
- Ha a szűrő széles marad, kapcsoljuk be az iteratív indexszkennelést a
SET hnsw.iterative_scan = relaxed_orderparanccsal: a gráf addig jár, amíg a LIMIT betelik, ésstrict_orderakkor jön, amikor a távolsági sorrendnek pontosnak kell lennie. - Korlátozzuk a munkát. A
hnsw.max_scan_tuplesalapértelmezett értéke 20.000, ahnsw.scan_mem_multiplierpedig awork_memegy szorzója, így a szelektív szűrő véges szkenneléssé romlik, nem végtelenné. - Sok különböző értéknél részleges index kell értékenként, vagy listaparticionálni kell a táblát. A README azt is megjegyzi, hogy az egy közelítő indexet megosztó ügyfelek egymás találati arányát is befolyásolják, ez tehát partitionálási, nem hangolási érv.
Első lépések
A teljes felület SQL, és ez az oka annak, hogy egy saját API-val dolgozó rendszer helyett ezt érdemes választani. Az alábbi kódrészlet egy éles tábla formája: rögzített dimenziójú oszlop, pontos index a szűrőre, közelítő index a vektorra, és az az egy beállítás, amely eldönti, hogy a szűrt lekérdezés röviden tér-e vissza.
CREATE EXTENSION IF NOT EXISTS vector;
-- The dimension is part of the type, so every row has to match it.
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
tenant_id text NOT NULL,
embedding vector(1536)
);
-- Exact index on the filter first: for a selective tenant it answers the
-- whole query and the approximate index is never consulted.
CREATE INDEX ON chunks (tenant_id);
-- Bulk load with COPY, then build the approximate index on top of the data.
CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- A filter matching 10% of rows with ef_search = 40 returns about four rows,
-- so the scan has to be allowed to continue past its first pass.
SET hnsw.iterative_scan = relaxed_order;
SET hnsw.ef_search = 100;
SELECT id
FROM chunks
WHERE tenant_id = 'acme'
ORDER BY embedding <=> (SELECT embedding FROM chunks WHERE id = 42)
LIMIT 10;Három döntés érdemes a védelmére az alábbi kódban. A dimenzió a típus része, így egy másik beágyazó modell által írt sor már az INSERT nél bukik, nem a lekérdezés idején. A közelítő index az adatok után épül, mert egy üres táblán létrehozott HNSW-gráfnak nincs mit összekötnie, és úgyis újraépítenék. A próbavektor pedig subselectből jön, abból a formából, amit a lekérdezéstervező elfogad; ugyanez a lekérdezés kifejezéssel az ORDER BY-ban figyelmeztetés nélkül szekvenciális szkennelésre esik vissza.
Teljesítmény
A memória az egész teljesítmény-történet. Egy vektoroszlop dimenciónként 4 bájtot és 8 bájtos fejlécet foglal, így 1536 dimenzió index nélkül körülbelül 6 KB soronként, és a AWS mérése szerint egy 100 millió 768 dimenziós vektorral dolgozó teljes pontosságú HNSW-index 367 GB, nagyjából 3,7 GB milliónként. A többi típus pontosan ezért a számért lett kitalálva.
| Típus | Bájt dimenciónként | Indexelhető korlát | Mit jár érte |
|---|---|---|---|
vector | 4 | 2.000 dim | az alap; a rajta végzett pontos keresés pontos találati arányt ad |
halfvec | 2 | 4.000 dim | feleakkora index, a AWS mérése szerint szinte nulla találati arány-veszteség |
bit | 1/8 | 64.000 dim | Hamming a előjel-biteken, a találati arányhoz újrasorrendezés kell |
sparsevec | 8 nem-nulla elemenként | 1.000 nem-nulla | ritka beágyazások, L2, koszinusz, belső szorzat és L1 |
A AWS a legtisztább nyilvános számokat közölte erről: VectorDBBench v0.3.4, top_k=100, Aurora PostgreSQL 18.4, pgvector 0.8.0. A 768 dimenziós LAION 100M esetén egy 128 GB-os r8g.4xlarge egy 367 GB-os, teljes pontosságú HNSW-indexet tárolt, amelyet nem tudott a gyorsítótárban tartani: 3,4 lekérdezés másodpercenként hidegen, 10 párhuzamos kapcsolat mellett, 3.336 melegen, 0,965 találati arány, 16,1 óra építés. Az újrasorrendező bináris kvantizálás 38 GB-ra és 1,1 órára vitte le az indexet, másodpercenként 13,5 hideg és 895 meleg lekérést ért el, és ezt a találati arány fizette meg: 0,931-re.
Ugyanez a mérés hordozza az ellenpéldát is, ezért a számait a módszertanukkal együtt kell olvasni. A Cohere 10M esetén, ahol a 768 dimenziós beágyazások a nulla közel csoportosulnak, a bináris kvantizálás 3000 jelölt újrasorrendezésével ért csak 0,93 találati arányt, és másodpercenként 16 lekérdezésre esett vissza 1640 ms p99 mellett, míg egy 384 GB-os gépen a teljes pontosságú HNSW 6930 lekérést adott 0,952 találati aránnyal. A kvantizálás eloszlásfüggő: validálni kell a saját beágyazásokon, vagy halfvec használni, és felezni az indexet találgatás helyett.
- Az
maintenance_work_memértékét emelni kell HNSW-index építése előtt; a Postgres Notice-t ír, amikor a gráf már nem fér bele, és a README óva int attól, hogy a kiszolgáló memóriájáig emeljük. - Töltsünk
COPYparanccsal, indexeljünk utána, és éles környezetbenCREATE INDEX CONCURRENTLYhasználjunk, hogy az építés ne blokkolja az írásokat. - A HNSW-index VACUUM-ja eltarthat egy ideig; a dokumentált gyorsítás, hogy előbb
REINDEX INDEX CONCURRENTLY, utána vacuum. - A vízszintes skálázást kölcsönözzük, nem építjük: a replikáció és a pillanatnyi visszaállítás a WAL-ból jön, a shardoláshoz pedig a README a Citusra, a PgDogra vagy a listaparticionálásra mutat.
Ahol megakad
A gyengeségek strukturálisak, nem befejezetlenek. Minden egy Postgres-csomóponton fut, így az index, a heap és a gyorsítótár ugyanazért a memóriáért verseng, és amelyik index nem fér bele, az előbb I/O-probléma lesz, csak utána találati arány-probléma. A közelítő keresés és a szelektív szűrők iteratív szkenneléssel is vitáznak, mert a véges szkennelés véges marad. A vacuum és az indexkarbantartás ennek az adatbázisnak a munkája, nem valaki másé. Beépített shardolás pedig nincs: a vízszintes skálázás replikákat, particionálást vagy egy bővítményt jelent.
| Alternatíva | Üzemeltetési forma | Üzemeltetési teher | Hol jobb |
|---|---|---|---|
| Qdrant | Külön Rust-szerver vagy a gyártó felhője | Még egy kluster javításra, mentésre, biztonságra | Payload-szűrés és kvantizálás nagy volumenű találati arányra hangolva |
| Weaviate | Külön szerver GraphQL API-val vagy a gyártó felhője | Ugyanez még egyszer, plusz saját modulkonfiguráció | Hibrid keresés és vektorosítás egy helyen konfigurálva |
| Chroma | Beágyazva a folyamatba vagy kis önálló szerverként | Szinte semmi, de Postgres sincs | A legrövidebb út a prototípustól a futó rendszerig |
A őszinte határ: a pgvector addig nyer, amíg a vektorok a csapat amúgy is tárolt adatainak egy oszlopa, és akkor veszít, amikor egy lekérdezésnek ugyanabban a memóriában kell tartania egy nagy gráfot, egy szűrt szkennelést és az alkalmazás munkakészletének többi részét. A AWS ezt a határt 100 millió vektornál 367 GB indexben mérte meg, és kvantizálással, valamint particionálással kerülte meg. Akik ezt a cserét nem akarják magukra vállalni, négy kijáratuk van: halfvec, újrasorrendezéssel együtt futó bináris kvantizálás, ügyfél szerinti particionálás vagy egy külön rendszer, az első kettő pedig elég olcsó ahhoz, hogy a negyedikről való beszélgetés előtt ki kell próbálni.
Ítélet
A pgvector legyen az alapértelmezett válasz arra, hová kerüljenek a beágyazások, minden olyan csapatnál, amely már futtat Postgrest, és egy külön vektordatázisnak magának kell megindokolnia, miért kerüljön sorra. A bővítménynek van egy szokatlan tulajdonsága: a hibái azok a hibák, amiket a csapat már ismer egy adatbázisból — memónynyomás, karbantartási ablakok, egy csomópont írási teljesítménye. Mást csak akkor válassz, ha a méret vagy a késleltetési cél megnevezhető.
- Válaszd a pgvector-t, ha a vektorok olyan sorokat írnak le, amelyeket a csapat amúgy is tárol, és az ügyfélszigetelés, a kaszkádos törlés vagy a forrástáblával való JOIN tranzakciónak kell lennie.
- Válaszd, ha az anyag legfeljebb néhány tízmillió vektorból áll, és a szűrő elég szelektív ahhoz, hogy a szűrőoszlopon lévő B-tree vigye a lekérdezés java részét.
- Válaszd, ha az alternatíva egy második éles rendszer: a bővítmény örökli a már meglévő mentést, replikációt, megfigyelést és hozzáférés-kezelést, és nem ad hozzá új üzemeltetnivalót.
- Ne válaszd, ha egyetlen lekérdezésnek több száz gigabájtos gráfot és az alkalmazás munkakészletét is a memóriában kell tartania, hacsak a
halfvecvagy a bináris kvantizálás nincs már megmérve a valós beágyazásokon. - Ne válaszd, ha az igény több csomóponton át tartó folyamatos írási teljesítmény, vagy alacsony késleltetésű szűrt keresés több százmillió vektoron; az particionálás vagy kifejezetten erre épített rendszer, és a halogatás később migrációt fizettet.
Nem minden beágyazó modell olyan vektorokat ad, amelyek jól kvantizálhatók. Döntés előtt a saját adatokon kell validálni. — AWS Database Blog, 2026. augusztus 18.
Források
Gyakori kérdések
Ingyenes a pgvector használata?
Igen. A PostgreSQL licenc alatt jelenik meg, díj, open-core szétválasztás és fizetős terv nélkül, és egyre több hosztolt Postgres-szolgáltatónál előre telepítve érkezik. A lényeg a verzió: az iteratív indexszkenneléshez 0.8.0 vagy újabb kell.
Mikor érdemes HNSW-t használni IVFFlat helyett?
A HNSW jobb sebesség-találati arányt ad, üres táblán is létrehozható, mert nincs edzési lépése, viszont lassabban épül és több memóriát igényel. Az IVFFlat gyorsabban épül, de előbb adat kell hozzá; a README szerint lists = rows / 1000 egymillió sorig, afölé sqrt(rows), a probes pedig sqrt(lists)-zel kezdve.
Működik a pgvector WHERE feltétellel?
Igen, de közelítő indexnél a szűrő az indexszkennelés után fut, így egy szelektív feltétel kevesebb sort adhat vissza, mint amennyit a LIMIT kér. A dokumentált megoldások: B-tree a szűrőoszlopon, iteratív indexszkennelés a hnsw.iterative_scan kapcsolóval, részleges index értékenként és listaparticionálás sok különböző értékhez.
Hány vektort kezel a pgvector?
Egyetlen táblát a PostgreSQL 32 TB-os relációkorlátja és az határoz meg, mennyi fér a memóriába; a AWS 367 GB indexet mért 100 millió 768 dimenziós vektornál, és milliárdos nagyságrenden particionálást javasol. Efölött a README replikákat, Citust, PgDogot vagy listaparticionálást ajánl beépített shard-réteg helyett.