RAG mit PostgreSQL pgvector: Vektorsuche in der SQL-Datenbank
Für viele B2B-Projekte ist das Speichern von Vektordaten in einer dedizierten, neuen Vektordatenbank ein unnötiger administrativer Aufwand. Die quelloffene PostgreSQL-Erweiterung pgvector ermöglicht es, Vektordaten direkt in einer relationalen PostgreSQL-Datenbank zu speichern, zu indizieren und über Standard-SQL-Queries abzufragen. Dies kombiniert die bewährte Stabilität von SQL mit den Anforderungen moderner RAG-Systeme.
Warum PostgreSQL für Vektordaten?
- Keine neue Datenbank-Infrastruktur: Unternehmen müssen keine zusätzlichen Systeme (wie Pinecone oder Qdrant) lizenzieren, absichern und warten.
- Volle relationale Power (JOINs): Vektorsuchen können direkt in SQL mit relationalen Daten verknüpft werden. Sie können beispielsweise mit einer einzigen Abfrage nach Dokumenten suchen, die semantisch ähnlich sind und gleichzeitig zur Kategorie „Support“ gehören sowie vom Benutzer X eingesehen werden dürfen.
- ACID-Konformität: Änderungen an Vektordaten (z. B. das Aktualisieren von Dokument-Chunks) unterliegen denselben strengen Transaktionssicherheiten wie herkömmliche SQL-Daten.
SQL-Grundlagen mit pgvector
Nach der Aktivierung der Erweiterung stellt pgvector den neuen Datentyp vector zur Verfügung.
1. Tabelle erstellen
Wir definieren eine Tabelle, die den Text-Chunk und den dazugehörigen Vektor speichert. Die Dimension (hier 1536 für typische OpenAI- oder Cohere-Modelle) muss fest vorgegeben werden:
CREATE TABLE dokument_chunks (
id serial PRIMARY KEY,
dokument_id integer REFERENCES dokumente(id) ON DELETE CASCADE,
inhalt text NOT NULL,
embedding vector(1536) -- 1536-dimensionaler Vektor
);
2. Daten einfügen
Ein Vektor wird als Array von Fliesskommazahlen in eckigen Klammern übergeben:
INSERT INTO dokument_chunks (inhalt, embedding)
VALUES ('Die Kündigungsfrist beträgt drei Monate.', '[0.012,-0.034,0.789,...]');
3. Vektorsuche ausführen (Kosinus-Distanz)
Um die ähnlichsten Chunks zu einer Suchanfrage zu ermitteln, berechnet pgvector die Kosinus-Distanz mit dem Operator <=>. Die Abfrage sortiert nach aufsteigendem Abstand (kleinster Abstand = grösste Ähnlichkeit):
SELECT inhalt, embedding <=> '[0.010,-0.030,0.750,...]' AS distanz
FROM dokument_chunks
ORDER BY distanz
LIMIT 5;
Indizierung für Hochleistungs-Suchen
Bei grossen Datenmengen (mehrere Zehntausend Chunks) würde eine Suche ohne Index die CPU stark belasten. pgvector unterstützt zwei Indextypen zur Beschleunigung (Näherungssuche - ANN):
HNSW-Index (Hierarchical Navigable Small World)
HNSW baut einen Suchgraphen auf. Er ist extrem schnell und präzise, verbraucht aber mehr RAM und benötigt beim Erstellen länger.
- SQL-Befehl:
CREATE INDEX ON dokument_chunks
USING hnsw (embedding vector_cosine_ops);
IVFFlat-Index (Inverted File Flat)
IVFFlat unterteilt die Vektoren in Cluster. Er benötigt weniger Speicherplatz und baut sich schneller auf als HNSW, ist jedoch bei gleicher Abrufpräzision meist etwas langsamer im Retrieval.
HNSW vs. IVFFlat im direkten Vergleich
Die Wahl des Indextyps ist die wichtigste Performance-Entscheidung bei pgvector. Die folgende Tabelle stellt beide Verfahren gegenüber:
| Eigenschaft | HNSW | IVFFlat |
|---|---|---|
| Suchgeschwindigkeit | sehr hoch | hoch |
| Trefferpräzision (Recall) | sehr hoch | mittel–hoch |
| RAM-Verbrauch | hoch | gering |
| Aufbauzeit | länger | schnell |
| Eignung bei wachsenden Daten | gut (inkrementell) | Index muss neu aufgebaut werden |
| Empfehlung | Standard für Produktion | große, statische Bestände mit RAM-Limit |
Faustregel: Beginnen Sie mit HNSW, sofern genügend Arbeitsspeicher vorhanden ist. IVFFlat ist die richtige Wahl, wenn der RAM knapp ist und sich der Datenbestand selten ändert. Die Wahl der Distanzfunktion (vector_cosine_ops für Embeddings) muss in beiden Fällen zum Abfrageoperator passen.
Vektorsuche mit relationalem Filter (Metadaten)
Der grösste Vorteil von pgvector gegenüber reinen Vektordatenbanken ist die Kombination aus semantischer Suche und klassischem SQL-Filter in einer Abfrage. So beschränken Sie die Suche etwa auf Dokumente einer bestimmten Mandanten-ID – ein wichtiger Baustein für die Mandantentrennung in RAG-Systemen:
SELECT inhalt, embedding <=> '[0.010,-0.030,0.750,...]' AS distanz
FROM dokument_chunks
WHERE mandant_id = 42 -- relationaler Filter (Pre-Filtering)
ORDER BY distanz
LIMIT 5;
PostgreSQL nutzt hier zuerst den B-Tree-Index auf mandant_id, um die Treffermenge zu verkleinern, und wendet danach die Vektorsuche an. So bleibt garantiert, dass ein Nutzer niemals Chunks eines fremden Mandanten als Kontext erhält.
Praxisbeispiel: Naive vs. produktionsreife Konfiguration
Ein Team startet ein RAG-Projekt mit pgvector über einem Firmen-Wiki:
- Naiv (Prototyp): 50’000 Chunks ohne Index. Jede Suche führt einen vollständigen Sequential Scan aus, vergleicht also jeden Vektor einzeln. Bei wenigen Nutzern fällt das nicht auf – unter Last steigt die Antwortzeit auf mehrere Sekunden.
- Produktionsreif: Ein HNSW-Index wird angelegt, die Embedding-Dimension auf das tatsächlich genutzte Modell festgelegt und ein Pre-Filter auf
mandant_idgesetzt. Die Suchzeit sinkt von über zwei Sekunden auf wenige Millisekunden, und die Treffer bleiben mandantengetrennt.
Die Lehre: pgvector ist schnell aufgesetzt, entfaltet seine Stärke aber erst mit passendem Index, fixierter Dimension und relationalem Filter – dann ersetzt es für die meisten B2B-Fälle eine separate Vektordatenbank vollständig.
[!TIP] pgvector ist die perfekte B2B-Lösung zur Vermeidung von Infrastruktur-Wildwuchs. Unsere interaktive RAG-Demo auf allerate.dev nutzt pgvector im Backend für eine zuverlässige und performante Suche.
Häufig gestellte Fragen (FAQ)
Wie wird die pgvector-Erweiterung in PostgreSQL aktiviert?
Sofern pgvector auf dem Server installiert ist, lässt sich die Erweiterung in einer PostgreSQL-Datenbank ganz einfach mit dem SQL-Befehl `CREATE EXTENSION vector;` aktivieren.
Was ist der Unterschied zwischen `<=>` und `<->` in pgvector?
Der Operator `<=>` steht in pgvector für die Kosinus-Distanz (Kosinus-Ähnlichkeit gespiegelt). Der Operator `<->` berechnet die euklidische Distanz (L2-Abstand).
Ab welcher Datenmenge lohnt sich ein dedizierter Vektordatenbank-Dienst statt pgvector?
Für die meisten B2B-Anwendungen mit bis zu mehreren Millionen Chunks ist pgvector mit einem HNSW-Index völlig ausreichend und betrieblich am einfachsten. Erst bei sehr grossen Beständen (über zehn Millionen Vektoren) oder extremen Latenzanforderungen kann ein spezialisierter Dienst wie Qdrant oder Milvus Vorteile bei Skalierung und Sharding bieten.
Kann pgvector Hybrid Search (Vektor plus Keyword) ausführen?
Ja. Da pgvector Teil von PostgreSQL ist, lässt sich die Vektorsuche in einer einzigen Abfrage mit der Volltextsuche (`tsvector`/`tsquery`) kombinieren. Die Ergebnisse beider Suchen werden anschliessend über Reciprocal Rank Fusion (RRF) zusammengeführt – das ist die Grundlage für eine [Hybrid Search](/rag/hybrid-search/) ohne zusätzliches System.