Zurück zur Startseite

pgvector vs pgvectorscale vs VectorChord: Vergleich

Vergleichende Analyse von PostgreSQL-Erweiterungen für Vektorsuche: pgvector, pgvectorscale und VectorChord. Beschreibung der HNSW-, StreamingDiskANN- und RaBitQ-Algorithmen. Docker-Infrastruktur, Bulk-Loading von 1M Datensätzen, Benchmark-Vorbereitung.

Schlacht der PostgreSQL-Vektorindizes: Wer ist schneller?
Advertisement 728x90

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.

Google AdInline article slot

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.

Google AdInline article slot

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.

Google AdInline article slot

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

Advertisement 728x90

Weiterlesen