pgvector vs pgvectorscale vs VectorChord: Leistungsvergleich für Vektor-Suche in PostgreSQL
Vektor-Suche wandelt Texte in numerische Einbettungen um und findet semantisch ähnliche Dokumente mithilfe von Nähe-Metriken. Begriffe mit ähnlicher Bedeutung bilden in einem N-dimensionalen Raum Cluster. Ein klassisches Beispiel: König - Mann + Frau ≈ Königin verdeutlicht Vektor-Analogien.
Wichtige Metriken:
- Cosinus-Ähnlichkeit: Winkel zwischen Vektoren; normierte Vektoren liefern Ergebnisse, die äquivalent zu euklidischer Distanz sind.
- Euklidische Distanz: Gerade Linie zwischen zwei Punkten.
PostgreSQL-Erweiterungen implementieren ANN (Approximate Nearest Neighbor)-Suche mit IVFFlat, HNSW und spezialisierten Algorithmen.
Die besten Erweiterungen für Vektor-Suche
pgvector
Eine Open-Source-C-Erweiterung mit dem vector-Typ. Unterstützt Cosinus-Ähnlichkeit, L2-Distanz und Skalarprodukt. Index-Typen:
- IVFFlat: Vektor-Clustering.
- HNSW: Hierarchischer Graph, top-down grobe Suche.
Benötigt vollständiges Laden des Indexes in den RAM.
pgvectorscale
Eine Rust-basierte Schicht über pgvector (mit PGRX). Verwendet den StreamingDiskANN-Index (Anpassung von DiskANN), der Daten auf SSD speichert und den RAM-Verbrauch reduziert. Nutzt SBQ (Statistical Binary Quantization) zur Kompression.
Behauptete Performancesteigerung: 16-fach höhere Durchsatzrate bei 50 Mio. Vektoren mit Dimension 768.
pgvecto.rs
Komplett in Rust geschrieben, unterstützt Binär-, FP16- und INT8-Formate mit bis zu 65.535 Dimensionen. Der VBASE-Algorithmus ist optimiert für hybride Abfragen (Vektor + Filter + JOINs).
VectorChord
Der aktuelle Nachfolger von pgvecto.rs von TensorChord. Kombiniert RaBitQ (Randomized Binary Quantization) mit Reorderung. Speichert 26-mal mehr Daten bei gleichem Kosten-Niveau.
Alle nutzen den Standard-vector-Typ – Migration ist problemlos möglich.
Aufbau der Testumgebung
Drei Datenbanken per Docker Compose bereitstellen:
- pgvectorscale (timescale/timescaledb-ha:pg18):
services:
postgres:
image: timescale/timescaledb-ha:pg18
ports:
- "5432:5432"
volumes:
- pgdata:/home/postgres/pgdata
- ./db_init_pgv:/docker-entrypoint-initdb.d
Initialisierung:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS vectorscale;
- VectorChord (tensorchord/vchord-postgres:pg18-v1.1.1):
CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
Makefile für Orchestrierung:
COMPOSE := docker compose
PGV_FILE := docker-compose-pgv.yml
PGVS_FILE := docker-compose-pgvs.yml
VC_FILE := docker-compose-vc.yml
up-pgv:
$(COMPOSE) -f $(PGV_FILE) up --build -d
up-pgvs:
$(COMPOSE) -f $(PGVS_FILE) up --build -d
up-vc:
$(COMPOSE) -f $(VC_FILE) up --build -d
up: up-pgv up-pgvs up-vc
Einzigartige Dienstnamen und Ports sind zwingend erforderlich.
Erweiterung des Repositories für Massenoperationen
Die bulk_create-Methode in BaseRepository:
async def bulk_create(self, schemas: list[CreateSchemaType]) -> list[ModelType]:
instances = [
self.model(**self._normalize_embedding_format(schema.model_dump()))
for schema in schemas
]
self.session.add_all(instances)
await self.session.flush()
return instances
BulkCreateRequest-Schema:
class BulkCreateRequest(BaseModel):
documents: Annotated[
list[DocumentCreate],
Field(..., description='Liste der zu erstellenden Dokumente', min_length=1, max_length=500)
]
Endpunkt:
@router.post('/bulk', response_model=list[DocumentResponse], status_code=status.HTTP_201_CREATED)
async def bulk_create_documents(request: BulkCreateRequest):
async with transaction() as session:
repo = DocumentRepository(session)
created_docs = await repo.bulk_create(request.documents)
return created_docs
Vorbereitung auf Benchmarking
Datensatz: ag_news von Hugging Face (Überschriften → Einbettungen, Kategorie → Metadaten). Ziel: 1 Million Datensätze.
Abhängigkeiten:
uv add --dev datasets ollama aiohttp tqdm
Testkomponenten:
- Batch-Laden aus Datensätzen
- Generierung von Einbettungen via ollama
- Masseneinfügung in DB
- Latenzmessung für Suchabfragen
Die Struktur der Testklasse ermöglicht parallelen Vergleich aller Erweiterungen.
Wichtige Erkenntnisse
- Kompatibilität: Alle Erweiterungen nutzen den
vector-Typ; Code ist portabel. - Skalierbarkeit: pgvectorscale und VectorChord arbeiten mit Festplattenspeicher; pgvector benötigt RAM.
- Kompression: RaBitQ (26-fache Datendichte), SBQ für große Datensätze.
- Hybride Suche: VBASE in pgvecto.rs unterstützt Filter + JOINs.
- Leistung: StreamingDiskANN bietet 16-fach höhere Durchsatzrate bei über 50 Mio. Vektoren.
— Editorial Team
Noch keine Kommentare.