Jeder Vergleich „pgvector vs. Pinecone“ im Internet endet irgendwann in einem Benchmark-Diagramm mit rohen Queries-per-Second bei einer festen Vektoranzahl, als ob diese Zahl allein die Architektur Ihres Retrieval-Systems bestimmen sollte. Das sollte sie nicht. Teams, die ihre Wahl der Vektordatenbank nach sechs Monaten bereuen, bereuen sie fast nie wegen des rohen Durchsatzes — sie bereuen sie, weil sie auf Basis eines Benchmarks entschieden haben, statt zu fragen, ob ihre gefilterten Abfragen, ihre operative Personalausstattung oder ihre Konsistenzanforderungen tatsächlich zu dem passten, was sie gewählt haben.
Die ehrliche Version dieser Entscheidung hat drei echte Eingangsgrößen, und keine davon ist „welches ist isoliert betrachtet schneller“: Wie groß wird der Korpus tatsächlich werden, wie komplex sind die Filter, die zusammen mit der Ähnlichkeitssuche laufen müssen, und wie viel dediziertes Betriebsbudget gibt es, um ein neues Infrastrukturstück zu betreiben und zu optimieren. Beantworten Sie diese drei Fragen zuerst, und die Frage pgvector versus dedizierte Datenbank beantwortet sich weitgehend von selbst — nicht weil eines universell besser ist, sondern weil sie für tatsächlich unterschiedliche Punkte auf diesen drei Achsen optimiert sind.
Sie lernen:
- Was pgvector tatsächlich ist und was „Vektorsuche innerhalb von Postgres“ mechanisch wirklich bedeutet
- Die echten Abwägungen zwischen den Indextypen HNSW und IVFFlat von pgvector
- Warum Filterkomplexität und nicht die rohe Vektoranzahl oft der entscheidende Faktor ist
- Was sich operativ ändert, wenn Sie Ihrem Stack eine dedizierte Vektordatenbank hinzufügen
- Ein konkretes Entscheidungsframework basierend auf Korpusgröße, Filteranforderungen und Ops-Budget
- Wie Sie Recall und Latenz tatsächlich auf Ihren eigenen Daten messen, statt einem Vendor-Diagramm zu vertrauen
Inhaltsverzeichnis
- Was pgvector tatsächlich ist
- Die Indextypen von pgvector: HNSW vs. IVFFlat
- Warum Filterkomplexität wichtiger ist als die Vektoranzahl
- Was Ihnen eine dedizierte Vektordatenbank tatsächlich bringt
- Das Entscheidungsframework
- Recall und Latenz auf Ihren eigenen Daten messen
- pgvector in Produktion betreiben
- Häufige Fallstricke
Was pgvector tatsächlich ist
pgvector ist eine Postgres-Erweiterung, die einen vector-Spaltentyp und eine Reihe von Distanzoperatoren hinzufügt — <-> (Euklidisch/L2), <=> (Kosinusdistanz), <#> (negatives inneres Produkt) — plus Indextypen, die speziell für die approximative Nearest-Neighbor-Suche über diese Spalten entwickelt wurden. Es ist kein angeflanschter Nebenprozess; die Vektoren liegen in einer normalen Tabelle, zusammen mit allen relationalen Spalten, die diese Zeile bereits beschreiben, und eine Ähnlichkeitsabfrage ist eine normale SQL-Abfrage mit einem ORDER BY auf einem Distanzoperator.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
tenant_id INT NOT NULL,
published_at TIMESTAMPTZ NOT NULL,
content TEXT NOT NULL,
embedding VECTOR(1536)
);
SELECT id, content
FROM documents
WHERE tenant_id = 42
ORDER BY embedding <=> '[0.012, -0.034, ...]'::vector
LIMIT 10;
Das ist das gesamte Versprechen in einer einzigen Abfrage: Postgres-Vektorsuche, die sich natürlich mit WHERE, JOIN, Transaktionen und jedem anderen relationalen Werkzeug zusammensetzt, das bereits im Stack vorhanden ist, statt in einem separaten System zu leben, das mit der Source of Truth synchron gehalten werden muss. Weil das Embedding in derselben Zeile wie alles andere lebt — dieselbe Transaktion, die ein neues Dokument einfügt, kann sein Embedding berechnen und speichern, ohne einen separaten Schreibpfad konsistent halten zu müssen — gibt es kein Eventual-Consistency-Fenster zwischen „das Dokument existiert“ und „das Dokument ist durchsuchbar“. Das ist im Vergleich zur Synchronisierung einer Source-of-Truth-Datenbank in einen separaten Suchindex eine echte, wenn auch oft unterschätzte, Korrektheitseigenschaft. Genau dort, wo diese Kombinierbarkeit ihre Stärke hat, zeigen sich auch ihre Grenzen, wie unten beschrieben.
Die Indextypen von pgvector: HNSW vs. IVFFlat
Ohne Index ist ORDER BY embedding <=> ... eine exakte Nearest-Neighbor-Suche — sie berechnet die Distanz zu jeder Zeile und sortiert, was korrekt ist, aber linear mit der Tabellengröße skaliert. Ab einigen Zehntausend Zeilen wird das langsam genug, dass ein approximativer Index nötig wird, und pgvector bringt zwei davon mit.
IVFFlat partitioniert den Vektorraum über k-means in eine feste Anzahl von Clustern (lists), und eine Abfrage durchsucht nur die probes nächstgelegenen Cluster zum Query-Vektor statt der gesamten Tabelle. Er ist günstiger zu bauen und kleiner auf der Festplatte als HNSW, muss aber nachdem bereits eine repräsentative Datenmenge geladen wurde gebaut werden (ein IVFFlat-Index, der auf einer leeren oder nicht repräsentativen Tabelle erstellt wird, erzeugt schlecht geformte Cluster), und der Recall verschlechtert sich messbar, wenn neue Daten hinzugefügt werden, ohne neu zu bauen.
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
SET ivfflat.probes = 10; -- higher = better recall, slower query
HNSW (Hierarchical Navigable Small World) baut eine mehrschichtige Graphstruktur auf, die nahe Vektoren miteinander verbindet, und ist zur Standardempfehlung für neue pgvector-Deployments geworden, weil es nicht den Vorbehalt „erst nach dem Laden repräsentativer Daten bauen“ hat, den IVFFlat mitbringt, und weil es typischerweise einen spürbar besseren Recall bei vergleichbarer Query-Latenz liefert. Der Preis dafür ist ein langsamerer, speicherintensiverer Build-Prozess und ein größerer Footprint auf der Festplatte als IVFFlat bei derselben Vektoranzahl.
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
SET hnsw.ef_search = 40; -- higher = better recall, slower query
Beide Indextypen sind approximativ — sie tauschen eine kleine Menge Recall gegen große Geschwindigkeitsgewinne ein, und beide bieten einen abstimmbaren Regler (probes für IVFFlat, ef_search für HNSW), mit dem Sie sich zur Abfragezeit entlang dieser Recall-gegen-Latenz-Kurve bewegen können, ohne den Index neu zu bauen. Setzen Sie für neue Arbeiten standardmäßig auf HNSW; greifen Sie gezielt zu IVFFlat, wenn Build-Zeit oder Speicher während der Indexkonstruktion der begrenzende Faktor sind.
Warum Filterkomplexität wichtiger ist als die Vektoranzahl
Die meisten Vergleiche fixieren sich auf die rohe Vektoranzahl als entscheidenden Faktor, aber das schwierigere Problem in einer echten Anwendung ist fast immer gefilterte Ähnlichkeitssuche — „finde die 10 ähnlichsten Dokumente für diesen Tenant, veröffentlicht in den letzten 30 Tagen, ohne archivierte“ — und nicht die ungefilterte Suche über den gesamten Korpus.
Das ist wichtig, weil Approximate-Nearest-Neighbor-Indizes und WHERE-Filter nicht automatisch gut zusammenspielen. Wenn der Filter nachdem der ANN-Index seine Top-Kandidaten zurückgegeben hat angewendet wird, kann ein hochselektiver Filter dazu führen, dass deutlich weniger als das angeforderte LIMIT übrig bleibt, weil die ANN-Suche ihre nächsten Nachbarn gefunden hat, bevor sie wusste, dass die meisten davon herausgefiltert würden. pgvector geht damit vernünftig um, weil es eine echte relationale Datenbank ist — der Query Planner kann entscheiden, zuerst mit einem normalen Index auf tenant_id und published_at zu filtern und erst dann die Distanzsuche über die reduzierte Menge laufen zu lassen, genau die Art von Planner-Entscheidung, deren Lesen und Prüfen der EXPLAIN ANALYZE-Leitfaden vermittelt:
EXPLAIN ANALYZE
SELECT id, content
FROM documents
WHERE tenant_id = 42
AND published_at > now() - interval '30 days'
AND status != 'archived'
ORDER BY embedding <=> '[0.012, ...]'::vector
LIMIT 10;
Wenn der Plan zeigt, dass der tenant_id-/published_at-Filter vor dem ANN-Index-Scan ausgeführt wird und die Kandidatenmenge komfortabel verengt, ist Filtern hier günstig. Wenn der Korpus von einem Tenant dominiert wird oder der Filter auf einem Feld mit geringer Selektivität liegt, kann der Planner darauf zurückfallen, mehr vom HNSW-Graphen zu scannen als erwartet, um sowohl den Filter als auch das LIMIT gemeinsam zu erfüllen — und das ist ein echter Kostenfaktor, den man messen und nicht wegnehmen sollte. Viele speziell entwickelte Vektordatenbanken behandelten gefilterte Suche historisch entweder durch Vorfilterung der gesamten Kandidatenmenge (teuer) oder Nachfilterung nach der ANN-Suche (ungenau), und das Schließen dieser Lücke war in der gesamten Kategorie ein aktives Entwicklungsfeld — es lohnt sich, das aktuelle Verhalten eines konkreten Vendors bei gefilterter Suche zu prüfen, statt in die eine oder andere Richtung auf den allgemeinen Ruf zu vertrauen.
Was Ihnen eine dedizierte Vektordatenbank tatsächlich bringt
Eine dedizierte Vektordatenbank — Pinecone, Weaviate, Qdrant, Milvus — verdient ihren Platz durch einen tatsächlich anderen Satz technischer Prioritäten als eine allgemeine relationale Datenbank, die um einen Vektortyp erweitert wurde:
- Horizontale Skalierung von Anfang an eingeplant. Das Sharding eines Vektorindex über viele Knoten hinweg, um einen Korpus im Bereich von Hunderten Millionen bis Milliarden Vektoren zu bedienen, ist in diesen Systemen ein gelöstes, produktisiertes Problem; pgvector über die praktischen Grenzen einer einzelnen Postgres-Instanz hinaus zu skalieren bedeutet, manuell zu sharden oder sich auf Postgres-spezifische Skalierungswerkzeuge (Citus, Read Replicas) zu stützen, die nicht speziell für Vektor-Workloads entwickelt wurden.
- Zweckgebundene operative Werkzeuge. Live-Index-Rebuilds ohne Downtime, hybride dichte-plus-sparse Suche und Multi-Tenant-Namespace-Isolation sind erstklassige, gut dokumentierte Features statt etwas, das aus allgemeinen Bausteinen zusammengesetzt wird.
- Managed Infrastructure als Standard. Die meisten dedizierten Optionen werden als Managed Service angeboten — keine Kapazitätsplanung für den Speicherbedarf von HNSW, kein manuelles Index-Tuning, dafür aber eine neue Vendor-Beziehung, eine neue Rechnung und ein neues System, das überwacht und abgesichert werden muss.
- Ökosystem-Integrationen. Managed Vektordatenbanken liefern oft erstklassige Connectoren für populäre Embedding- und RAG-Frameworks, was bei einem neuen Projekt echte Integrationszeit sparen kann im Vergleich dazu, pgvector per Hand in dieselben Frameworks einzubinden — wobei diese Lücke kleiner geworden ist, je stärker die Unterstützung im Ökosystem rund um pgvector gereift ist.
Nichts davon macht eine dedizierte Vektordatenbank strikt „besser“ — es macht sie zum richtigen Werkzeug genau dann, wenn Korpusgröße oder Feature-Anforderungen eine Schwelle überschreiten, die eine einzelne Postgres-Instanz, egal wie gut getunt, nicht dafür ausgelegt war zu nehmen.
| pgvector | Dedizierte Vektordatenbank | |
|---|---|---|
| Bester Korpusbereich | bis etwa ~10M Vektoren problemlos | Zehnmillionen bis Milliarden |
| Komplexe relationale Filter | nativ — derselbe Query Planner wie für alles andere | oft angeflanscht, besser werdend, aber vendorabhängig |
| Konsistenz mit Quelldaten | dieselbe Transaktion, keine Sync-Verzögerung | separater Schreibpfad, Sync-/Konsistenzfenster |
| Ops-Overhead | nahezu null, wenn Sie ohnehin Postgres betreiben | ein neues Managed- oder Self-Hosted-System, das betrieben werden muss |
| Horizontale Skalierung | manuell (Sharding, Citus) | eingebaut |
| Kostenmodell | Teil der bestehenden Postgres-Ausgaben | separate, nutzungsbasierte Abrechnung |
Nutzen Sie diese Tabelle als schnellen Plausibilitätscheck gegen das folgende Framework, nicht als die Entscheidung selbst — tatsächliche Filterkomplexität und gemessener Recall auf Ihren eigenen Daten haben Vorrang vor jeder allgemeinen Tabelle wie dieser.
Das Entscheidungsframework
Gewichten Sie diese drei Achsen gemeinsam statt jede für sich isoliert:
Korpusgröße. Unter einigen Millionen Vektoren bewältigt pgvector auf vernünftig ausgestatteter Hardware sowohl Build-Zeit als auch Query-Latenz für die meisten Anwendungen problemlos. Zehnmillionenbereich erfordert bereits echte Aufmerksamkeit beim HNSW-Tuning (m, ef_construction, verfügbarer RAM für den Graphen). Hunderte Millionen bis Milliarden sind der Bereich, in dem die Geschichte der horizontalen Skalierung eines dedizierten Systems wichtiger zu werden beginnt als jeder Tuning-Regler auf einem einzelnen Knoten ausgleichen könnte.
Filterkomplexität. Einfache Filter mit geringer Kardinalität (eine Handvoll Tenant-IDs, ein Boolean-Flag) sind in beiden Architekturen günstig. Komplexe Filterkombinationen mit hoher Kardinalität, die sich häufig ändern, sind der Bereich, in dem das echte relationale Datenbanksein der stärkste strukturelle Vorteil von pgvector ist — der Query Planner weiß bereits, wie beliebige Filterkombinationen optimiert werden, denn genau dafür wurde die gesamte Disziplin allgemeiner Datenbanken über Jahrzehnte verfeinert.
Betriebsbudget. Wenn das Team Postgres bereits betreibt und überwacht, ist das Hinzufügen von pgvector operativ fast kostenlos — es ist ein CREATE EXTENSION-Statement und ein Index, kein neues System. Eine dedizierte Vektordatenbank aufzusetzen ist ein echtes neues Infrastrukturstück: ein neues Deployment, neue Zugangsdaten und Netzwerkpfade, die abgesichert werden müssen, ein neues Dashboard zum Überwachen und ein neuer Fehlermodus, für den es ein On-Call-Runbook geben muss. Diese Kosten lohnen sich, wenn Korpusgröße oder Feature-Anforderungen sie tatsächlich erfordern, und sind reiner Overhead, wenn nicht.
Eine konkrete Faustregel: Beginnen Sie mit pgvector, wenn der Korpus unter grob zehn Millionen Vektoren liegt, die Filter auf Daten basieren, die bereits relational sind (Tenant, Datum, Status, Berechtigungen), und das Team nicht bereits ein separates spezialisiertes Dateninfrastruktur-Team betreibt. Wechseln Sie zu einer dedizierten Vektordatenbank, wenn das Korpuswachstum klar weit über diesen Bereich hinausgeht, wenn hybride oder hierarchische Suchfeatures zu einer harten Anforderung werden oder wenn die Last der Vektorsuche groß und spiky genug ist, dass ihre Isolation vom Ressourcenbudget der primären transaktionalen Datenbank aus sich selbst heraus wertvoll wird.
Recall und Latenz auf Ihren eigenen Daten messen
Jeder Vendor-Benchmark verwendet einen Datensatz und eine Query-Verteilung, die den tatsächlichen Embeddings, Filtern oder der Korpusform Ihrer Anwendung möglicherweise nicht ähneln. Der einzige Benchmark, dem man vertrauen sollte, ist einer, der gegen echte Daten (oder realistische synthetische Daten) ausgeführt wird:
import time
import numpy as np
def recall_at_k(approx_results, exact_results, k=10):
approx_ids = set(r[0] for r in approx_results[:k])
exact_ids = set(r[0] for r in exact_results[:k])
return len(approx_ids & exact_ids) / k
# Compare HNSW results against an exact (no-index) scan on the same query
exact = conn.execute(
"SELECT id FROM documents ORDER BY embedding <=> %s LIMIT 10", [qvec]
).fetchall()
approx = conn.execute(
"SET hnsw.ef_search = 40; SELECT id FROM documents ORDER BY embedding <=> %s LIMIT 10", [qvec]
).fetchall()
print(recall_at_k(approx, exact))
Führen Sie das über eine repräsentative Stichprobe echter Abfragen aus, nicht nur über ein handverlesenes Beispiel, und variieren Sie ef_search oder probes gegen die gemessene Latenz, um herauszufinden, wo die Recall-Kurve für Ihre tatsächlichen Daten abflacht — diese Zahl sollte die ef_search-/probes-Einstellung in Produktion bestimmen, nicht ein aus der Dokumentation übernommener Standardwert.
pgvector in Produktion betreiben
pgvector in einem Notebook zum Laufen zu bringen ist eine Fünf-Minuten-Aufgabe; pgvector-Produktions-Workloads zuverlässig zu betreiben bedeutet, den Index genauso zu behandeln wie jedes andere performancekritische Postgres-Objekt — geplant, überwacht und gezielt neu aufgebaut, statt ihn nach dem ersten CREATE INDEX sich selbst zu überlassen. Das Erstellen eines HNSW-Index auf einer Tabelle mit Millionen Zeilen kostet reale Zeit und Speicher, und ein normales CREATE INDEX blockiert währenddessen Schreibzugriffe auf die Tabelle — dasselbe Lock-Verhalten, das jeder Postgres-Index-Build hat und das im Leitfaden zu Zero-Downtime-Migrationen ausführlicher behandelt wird. Verwenden Sie CREATE INDEX CONCURRENTLY für einen Vektorindex auf einer Live-Tabelle genauso, wie Sie es für jeden anderen Indextyp tun würden, und planen Sie realistische Zeit dafür ein — HNSW-Builds sind CPU- und speicherintensiv genug, dass sie deutlich länger dauern als ein äquivalenter B-tree-Build bei derselben Zeilenanzahl.
Auch maintenance_work_mem ist hier wichtiger als bei einem typischen B-tree-Build — die HNSW-Konstruktion ist speicherhungrig, und ein zu knapp bemessenes maintenance_work_mem kann den Build dramatisch langsamer machen als nötig. Erhöhen Sie es gezielt für die Build-Session statt global, wenn das normale Arbeitsspeicherbudget des Servers enger ist als das, was ein großer HNSW-Build benötigt.
Häufige Fallstricke
Fehler: Einen IVFFlat-Index bauen, bevor repräsentative Daten geladen wurden. Der k-means-Clustering-Schritt braucht echte Daten, um gute Cluster zu bilden; ein Index, der auf einer leeren oder winzigen Tabelle erstellt wird, erzeugt schlechte Cluster, die den Recall dauerhaft verschlechtern, bis neu gebaut wird. Lösung: Laden Sie zuerst eine repräsentative Stichprobe oder setzen Sie standardmäßig auf HNSW, das diese Reihenfolgeanforderung nicht hat.
Fehler: Anzunehmen, dass eine gefilterte Abfrage mit einem hochselektiven Filter automatisch schnell ist. Ein sehr selektiver Filter in Kombination mit einem ANN-Index kann in manchen Plänen bedeuten, dass mehr vom Index gescannt werden muss als erwartet, um sowohl den Filter als auch das Zeilenlimit zu erfüllen. Lösung: Führen Sie EXPLAIN ANALYZE auf Ihren tatsächlichen gefilterten Abfragen aus, nicht nur auf der ungefilterten Ähnlichkeitssuche.
Fehler: Eine dedizierte Vektordatenbank allein auf Basis eines Benchmark-Diagramms auszuwählen. Vendor-Benchmarks entsprechen selten Ihrer Filterkomplexität, Embedding-Dimensionalität oder Query-Verteilung. Lösung: Messen Sie Recall und Latenz auf Ihren eigenen Daten, bevor Sie sich auf eine der beiden Architekturen festlegen.
Fehler: Die Entscheidung pgvector-vs.-dediziert als dauerhaft und unumkehrbar zu behandeln. Viele Teams starten mit pgvector, und der spätere Migrationspfad zu einem dedizierten System — sobald Korpusgröße oder Feature-Anforderungen ihn wirklich rechtfertigen — ist ein gut ausgetretener Weg und keine seltene Ausnahme. Lösung: Setzen Sie zuerst standardmäßig auf die Option mit den geringeren Betriebskosten, sofern Sie nicht bereits klare Belege dafür haben, dass der Korpus die Schwelle überschreiten wird, ab der sie nicht mehr ausreicht.
Fehler: Das Tuning von maintenance_work_mem für den Index-Build zu überspringen. Ein langsamer, speicherarmer HNSW-Build kann dramatisch länger dauern als nötig und in Extremfällen auf eine Weise spillen, die die Build-Qualität verschlechtert. Lösung: Erhöhen Sie maintenance_work_mem für die Build-Session, bevor Sie ein großes CREATE INDEX CONCURRENTLY ... USING hnsw ausführen.
Zum Schluss
pgvector und eine dedizierte Vektordatenbank konkurrieren nicht um denselben Job — sie sind für unterschiedliche Punkte bei Korpusgröße, Filterkomplexität und Betriebsbudget optimiert, und die richtige Wahl ergibt sich daraus, ehrlich zu sein, wo Ihre tatsächliche Anwendung auf diesen drei Achsen liegt, statt daraus, welches System ein Benchmark-Diagramm gewonnen hat. Beginnen Sie mit pgvector, wenn der Korpus moderat ist und die Filter relational geprägt sind, denn operativ ist es auf einer Infrastruktur, die Sie wahrscheinlich ohnehin bereits betreiben, fast kostenlos; wechseln Sie zu einem dedizierten System, wenn Skalierung oder Feature-Anforderungen ihm wirklich entwachsen, und validieren Sie diesen Schritt mit Recall- und Latenzzahlen, die auf Ihren eigenen Daten gemessen wurden und nicht auf denen anderer.
Haben Sie den Recall auf Ihren eigenen Abfragen tatsächlich gemessen, oder läuft Ihre Indexkonfiguration immer noch mit den Standardwerten aus der Dokumentation?
