pgvector: Vektorsuche in PostgreSQL
Was dieser Artikel behandelt
- Was pgvector ist und warum es eine PostgreSQL-Erweiterung für Vektorsuche ist.
- Wie Du pgvector installierst und den
vector-Datentyp nutzt. - Welche Index-Typen es gibt und wann Du IVFFlat oder HNSW wählst.
- Wie Du Vektoren in SQL speicherst und abfragst.
- Wo pgvector im Vergleich zu Chroma und Qdrant steht.
Einleitung
Wenn Du bereits PostgreSQL in Deinem Projekt einsetzt, brauchst Du keine neue Vektordatenbank. pgvector ist eine Erweiterung für PostgreSQL, die Vektorsuche direkt in Deiner bestehenden Datenbank ermöglicht. Du speicherst Embeddings neben Deinen normalen Tabellendaten und fragst sie mit SQL ab. Das spart Infrastruktur und vereinfacht Deinen Stack erheblich. Dieser Artikel zeigt Dir, wie Du pgvector installierst, Vektoren speicherst und Ähnlichkeitssuchen durchführst.
Warum brauche ich pgvector?
Viele Projekte nutzen bereits PostgreSQL für Benutzerdaten, Dokumente oder Konfigurationen. Wenn Du RAG hinzufügen willst, steht Du vor einer Entscheidung: eine zusätzliche Vektordatenbank wie Chroma oder Qdrant installieren oder die Vektorsuche in PostgreSQL integrieren. pgvector macht Letzteres möglich. Der größte Vorteil ist, dass Du Vektoren und normale Daten in derselben Datenbank hältst. Du kannst Join-Abfragen schreiben, die Vektorergebnisse mit Metadaten aus anderen Tabellen verknüpfen. Das ist mit dedizierten Vektordatenbanken oft umständlicher.
pgvector eignet sich besonders, wenn Dein Vektor-Bestand im Bereich von einigen Tausend bis wenigen Millionen Einträgen liegt. Für extrem große Datensätze oder spezielle Anforderungen wie GPU-Beschleunigung sind dedizierte Lösungen oft besser geeignet.
pgvector kurz erklärt
pgvector fügt PostgreSQL einen neuen Datentyp namens vector hinzu. Du definierst Spalten mit diesem Typ, speicherst Embeddings als Zahlenlisten und nutzt spezielle Operatoren für die Ähnlichkeitssuche. Die wichtigsten Operatoren sind:
<->für L2-Distanz (Euclidean Distance)<#>für Inner Product<=>für Cosine Similarity
Zusätzlich bietet pgvector zwei Index-Typen an, um die Suche bei großen Datenmengen zu beschleunigen: IVFFlat und HNSW. Beide Approximate Nearest Neighbor (ANN) Verfahren reduzieren die Suchzeit, indem sie nicht jeden Vektor vergleichen, sondern nur vielversprechende Kandidaten.
Für wen ist dieser Artikel gedacht?
Dieser Artikel richtet sich an Entwickler und Administratoren, die bereits PostgreSQL nutzen und RAG-Funktionen ergänzen möchten. Du solltest grundlegende SQL-Kenntnisse haben und wissen, was Embeddings sind. Wenn Du völlig neu bei Vektordatenbanken bist, lies zuerst den Überblicksartikel zu Vektordatenbanken und den Artikel zu Embedding-Modellen.
Wichtige Begriffe
| Begriff | Bedeutung |
|---|---|
vector | Datentyp in pgvector für Embeddings, z. B. vector(768) |
| Embedding | Zahlenvektor, der die Bedeutung eines Textes codiert |
| Cosine Similarity | Ähnlichkeitsmaß über den Winkel zwischen zwei Vektoren |
| L2 Distance | Euklidische Distanz zwischen zwei Vektoren |
| IVFFlat | Index-Typ, der den Raum in Cluster aufteilt (Inverted File) |
| HNSW | Index-Typ mit hierarchischem Graphen (Hierarchical Navigable Small World) |
| ANN | Approximate Nearest Neighbor, approximative Suche für Geschwindigkeit |
| Extension | PostgreSQL-Erweiterung, die neue Datentypen und Funktionen hinzufügt |
Installation
pgvector mit Docker
Der einfachste Weg ist ein Docker-Image, das pgvector bereits enthält. Mehr zu Docker findest Du im Artikel Docker Grundlagen.
docker run -d \
--name pgvector-db \
-e POSTGRES_PASSWORD=deinpasswort \
-e POSTGRES_DB=vektoren \
-p 5432:5432 \
pgvector/pgvector:pg16
pgvector auf einem bestehenden PostgreSQL
Wenn Du PostgreSQL bereits installiert hast, kompilierst Du pgvector aus dem Quellcode:
git clone https://github.com/pgvector/pgvector.git
cd pgvector
make
make install
Danach aktivierst Du die Erweiterung in PostgreSQL:
CREATE EXTENSION IF NOT EXISTS vector;
Erste Schritte
Tabelle mit Vektorspalte anlegen
CREATE TABLE dokumente (
id SERIAL PRIMARY KEY,
titel TEXT,
inhalt TEXT,
quelle TEXT,
embedding VECTOR(768)
);
Die Zahl in VECTOR(768) muss zur Dimension Deines Embedding-Modells passen. Wenn Du multilingual-e5-large nutzt, sind das 1024 Dimensionen.
Vektoren einfügen
INSERT INTO dokumente (titel, inhalt, quelle, embedding)
VALUES (
'Was ist lokale KI',
'Lokale KI läuft auf dem eigenen Rechner.',
'blog',
'[0.1, 0.2, 0.3, 0.4]'
);
In der Praxis erzeugst Du die Embeddings mit Python und fügst sie dann ein. Die Vektor-Liste wird als Text in eckigen Klammern übergeben.
Ähnlichkeitssuche
SELECT titel, quelle, embedding <=> '[0.1, 0.2, 0.3, 0.4]' AS distanz
FROM dokumente
ORDER BY embedding <=> '[0.1, 0.2, 0.3, 0.4]'
LIMIT 5;
Der Operator <=> berechnet die Cosine Similarity. Je kleiner der Wert, desto ähnlicher sind sich die Vektoren. Du sortierst aufsteigend und nimmst die ersten Ergebnisse.
Index-Typen: IVFFlat vs. HNSW
Ohne Index durchsucht PostgreSQL jeden Vektor sequenziell. Das wird bei mehreren Hunderttausend Einträgen langsam. Ein Index beschleunigt die Suche erheblich.
IVFFlat-Index
IVFFlat teilt den Vektorraum in Cluster auf. Bei der Suche wird nur der Cluster durchsucht, der zum Query-Vektor passt.
CREATE INDEX idx_dokumente_ivfflat
ON dokumente
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
Der Parameter lists bestimmt die Anzahl der Cluster. Ein guter Richtwert ist rows / 1000. Du musst den Index nach dem Einfügen der Daten neu aufbauen, damit die Cluster-Zentren gut gewählt werden.
HNSW-Index
HNSW baut einen hierarchischen Graphen auf. Er ist bei Suchanfragen oft schneller und genauer als IVFFlat, benötigt aber mehr Speicher und längere Build-Zeit.
CREATE INDEX idx_dokumente_hnsw
ON dokumente
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
Der Parameter m steuert die Graph-Verbindungen, ef_construction die Build-Qualität. Für die Suche kannst Du ef_search anpassen:
SET hnsw.ef_search = 100;
Welchen Index soll ich wählen?
HNSW ist in den meisten Fällen die bessere Wahl. Es bietet höhere Genauigkeit bei vergleichbarer Geschwindigkeit. IVFFlat ist einfacher zu verstehen und braucht weniger Speicher. Wenn Du neu startest, nimm HNSW. Wenn Du einen bestehenden IVFFlat-Index hast und zufrieden bist, bleibt es dabei.
pgvector mit Python nutzen
import psycopg2
from pgvector.psycopg2 import register_vector
conn = psycopg2.connect("dbname=vektoren user=postgres password=deinpasswort")
register_vector(conn)
cur = conn.cursor()
cur.execute("CREATE EXTENSION IF NOT EXISTS vector")
cur.execute("""
CREATE TABLE IF NOT EXISTS dokumente (
id SERIAL PRIMARY KEY,
titel TEXT,
embedding VECTOR(768)
)
""")
# Embedding aus Deinem Modell
embedding = [0.1] * 768
cur.execute(
"INSERT INTO dokumente (titel, embedding) VALUES (%s, %s)",
("Lokale KI", embedding)
)
cur.execute("""
SELECT titel, embedding <=> %s AS distanz
FROM dokumente
ORDER BY embedding <=> %s
LIMIT 5
""", (embedding, embedding))
results = cur.fetchall()
for row in results:
print(row)
conn.commit()
cur.close()
conn.close()
Vergleich mit Chroma und Qdrant
| Eigenschaft | pgvector | Chroma | Qdrant |
|---|---|---|---|
| Typ | PostgreSQL-Erweiterung | Eigenständige Vektordatenbank | Eigenständige Vektordatenbank |
| Setup | Einfach, wenn Postgres vorhanden | Sehr einfach per pip | Einfach per Docker |
| SQL-Unterstützung | Voll | Nein | Nein |
| Joins mit Tabellendaten | Ja | Nein | Nein |
| Skalierbarkeit | Mittel | Klein bis mittel | Hoch |
| Filterung | Voll (SQL WHERE) | Einfach | Erweitert (Payload) |
| Index-Typen | IVFFlat, HNSW | HNSW | HNSW |
| GPU-Support | Nein | Nein | Nein |
| Speicherbedarf | Mittel | Niedrig | Mittel |
pgvector glänzt, wenn Du ohnehin PostgreSQL nutzt und Vektoren mit relationalen Daten kombinieren willst. Für reine Vektorsuche bei großen Datenmengen sind Chroma und Qdrant oft die bessere Wahl. Mehr zur Kombination verschiedener Suchmethoden findest Du im Artikel zu Hybrid Search.
Typische Stolpersteine
- Falsche Vektor-Dimension: Die Spaltendefinition
VECTOR(768)muss exakt zur Dimension Deines Embedding-Modells passen. Ein Modell mit 1024 Dimensionen funktioniert nicht in einer 768-dimensionalen Spalte. - Kein Index bei großen Datenmengen: Ohne IVFFlat oder HNSW wird die Suche ab einigen Zehntausend Einträgen sehr langsam. Lege den Index an, bevor Du die Datenbank produktiv nutzt.
- IVFFlat-Index vor dem Einfügen erstellt: IVFFlat berechnet Cluster-Zentren beim Indexaufbau. Wenn die Tabelle noch leer ist, sind die Cluster schlecht. Füge zuerst die Daten ein und erstelle den Index danach.
- Falscher Operator-Class: Jeder Distanz-Maß braucht einen eigenen Operator-Class, z. B.
vector_cosine_opsfür Cosine Similarity. Ein falscher Class führt zu Fehlern oder falschen Ergebnissen. - Zu wenig
work_mem: HNSW-Builds benötigen Arbeitsspeicher. Bei großen Tabellen solltest Duwork_memtemporär erhöhen, etwa auf1GB. - Vergessene Extension: Nach einem PostgreSQL-Update oder Restore musst Du
CREATE EXTENSION vectorerneut ausführen, sonst sind die Vektor-Funktionen nicht verfügbar. - Embeddings als Text gespeichert: Speichere Vektoren immer als
vector-Typ, nicht als Text oder JSON. Nur dann funktionieren die Ähnlichkeitsoperatoren und Indizes. - Keine Vacuum-Wartung: Wie bei jeder PostgreSQL-Tabelle sind regelmäßige
VACUUM- undANALYZE-Läufe wichtig, damit der Query-Optimizer gute Pläne erstellt.
Hardware, Kosten und Sicherheit
pgvector läuft auf jedem Rechner, der auch PostgreSQL unterstützt. Für kleine Projekte reicht ein normaler Desktop oder ein kleiner VPS. Bei mehreren Millionen Vektoren solltest Du ausreichend RAM einplanen, da HNSW-Indizes im Speicher gehalten werden. Eine SSD ist empfehlenswert, besonders für den Indexaufbau.
Kosten: pgvector ist Open Source und kostenlos. Du zahlst nur für die Hardware oder den Server, auf dem PostgreSQL läuft.
Sicherheit: Da pgvector in PostgreSQL integriert ist, gelten dieselben Sicherheitsregeln. Nutze starke Passwörter, beschränke den Netzwerkzugriff und aktiviere SSL für Verbindungen. Wenn Du pgvector in Docker betreibst, exponiere den Port nicht öffentlich. Mehr zum sicheren Betrieb mit Docker findest Du unter Docker Grundlagen.
Weiterführende Links
- pgvector GitHub Repository
- pgvector Dokumentation
- Übersicht Vektordatenbanken
- RAG Grundlagen
- Lokales RAG
- Embedding-Modelle
- Chroma einrichten
- Qdrant einrichten
- Hybrid Search
- Docker Grundlagen
FAQ
Brauche ich eine separate Vektordatenbank, wenn ich pgvector nutze?
Nein. pgvector erweitert PostgreSQL um Vektorsuche. Wenn Du bereits PostgreSQL hast, brauchst Du keine zusätzliche Datenbank.
Welche PostgreSQL-Version wird unterstützt?
pgvector unterstützt PostgreSQL 13 und neuer. Aktuell werden die Versionen 13 bis 17 offiziell unterstützt.
Wie viele Vektoren verträgt pgvector?
Bis zu einigen Millionen Vektoren sind mit einem HNSW-Index gut möglich. Darüber hinaus wird der Speicherbedarf zum limitierenden Faktor.
Soll ich IVFFlat oder HNSW nutzen?
HNSW ist in den meisten Fällen die bessere Wahl, da es höhere Genauigkeit bei vergleichbarer Geschwindigkeit bietet. IVFFlat ist einfacher und speichereffizienter.
Kann ich pgvector mit Python nutzen?
Ja. Es gibt offizielle Bindings für psycopg2, psycopg3, SQLAlchemy und asyncpg. Die Bibliothek heisst pgvector-python.
Funktioniert pgvector mit Docker?
Ja. Es gibt ein offizielles Docker-Image unter pgvector/pgvector. Du kannst auch ein eigenes Image bauen, das pgvector auf einem PostgreSQL-Base-Image installiert.
Welche Distanz-Maße unterstützt pgvector?
L2 Distance (Euklidisch), Inner Product und Cosine Similarity. Jedes Mass hat einen eigenen Operator und einen eigenen Index-Operator-Class.
Kann ich Vektoren mit normalen Tabellendaten verknüpfen?
Ja, das ist einer der größten Vorteile von pgvector. Du kannst JOIN-Abfragen schreiben, die Vektorergebnisse mit Daten aus anderen Tabellen kombinieren.
Wie viel Speicher braucht ein HNSW-Index?
Das hängt von der Vektor-Dimension und der Anzahl der Einträge ab. Bei 768 Dimensionen und 1 Million Vektoren kann der Index mehrere Gigabyte gross werden.
Ist pgvector kostenlos?
Ja, pgvector ist Open Source unter der PostgreSQL-Lizenz und kostenlos. Du zahlst nur für die Hardware.
Kann ich pgvector mit Ollama kombinieren?
Ja. Ollama liefert das Sprachmodell, pgvector speichert die Embeddings. Dein Python-Skript verbindet beide über die Datenbankverbindung.
Muss ich den Index nach grossen Datenänderungen neu aufbauen?
HNSW-Indizes werden automatisch aktualisiert. Bei sehr grossen Änderungen kann ein Rebuild die Qualität verbessern. IVFFlat-Indizes sollten nach grossen Änderungen neu aufgebaut werden.
Quellen
- pgvector GitHub Repository
- pgvector Python Bindings
- PostgreSQL Dokumentation
- HNSW Paper von Malkov und Yashunin
- IVFFlat Erklärung in der pgvector README


