0Pricing
AI Engineering Academy · Leçon

pgvector : embeddings dans PostgreSQL

Activez l’extension pgvector dans PostgreSQL, créez une table contenant une colonne vectorielle, insérez des embeddings et exécutez des requêtes de plus proches voisins à l’aide de l’opérateur de distance cosinus .

pgvector : embeddings dans PostgreSQL est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

pgvector: Vector Search in PostgreSQL

pgvector is an open-source PostgreSQL extension that adds a vector data type and similarity search operators. It lets you store embeddings alongside your regular application data in the same database you already operate, avoiding a separate vector store.

This is ideal for teams that already use PostgreSQL and want to add semantic search without introducing a new infrastructure dependency.

Enabling the pgvector Extension

Install pgvector from the official repository or use a managed PostgreSQL provider that pre-installs it (Supabase, Neon, AWS RDS, Render). Then enable it in your database with a single SQL command — no restart required.

-- Run this once per database to enable the extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Verify it's installed
SELECT extname, extversion
FROM pg_extension
WHERE extname = 'vector';
-- Returns: vector | 0.7.0 (or similar)

Creating a Table with a Vector Column

Add a vector column by specifying vector(n) where n is the embedding dimension. You can combine it with regular PostgreSQL columns for metadata — this lets you filter by user_id, created_at, or any other field using standard SQL WHERE clauses.

CREATE TABLE documents (
    id          BIGSERIAL PRIMARY KEY,
    content     TEXT NOT NULL,
    category    TEXT,
    created_at  TIMESTAMPTZ DEFAULT NOW(),
    embedding   vector(1536)   -- must match your model dimension
);

-- Index on category for fast metadata filtering
CREATE INDEX ON documents (category);

SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'documents';

Inserting Embeddings from Python

Use the psycopg2 or asyncpg driver to insert rows with embeddings. Convert the Python list of floats to a string in the format '[0.1, 0.2, ...]' which pgvector parses correctly. The pgvector Python package provides a register_vector helper to handle this automatically.

import psycopg2
from pgvector.psycopg2 import register_vector
from openai import OpenAI

conn = psycopg2.connect('postgresql://user:pass@localhost/mydb')
register_vector(conn)
cur = conn.cursor()

client = OpenAI()

document = 'pgvector adds vector search to PostgreSQL.'
resp = client.embeddings.create(model='text-embedding-3-small', input=document)
embedding = resp.data[0].embedding

cur.execute(
    'INSERT INTO documents (content, category, embedding) VALUES (%s, %s, %s)',
    (document, 'database', embedding)
)
conn.commit()
print('Inserted document with embedding')

Cosine Similarity with the <=> Operator

pgvector adds three distance operators:

  • <=> — cosine distance (1 - cosine_similarity)
  • <-> — Euclidean (L2) distance
  • <#> — negative inner product (use for dot product similarity)

For text embeddings, use <=> (cosine distance). ORDER BY distance ASC returns the most similar documents first.

-- Find top 5 documents most similar to a query embedding
-- Replace '[0.1, 0.2, ...]' with the actual query vector
SELECT
    id,
    content,
    category,
    1 - (embedding <=> '[0.1, 0.2, 0.3]'::vector) AS cosine_similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, 0.3]'::vector
LIMIT 5;

Combining Vector Search with SQL Filters

One of pgvector's biggest advantages is that you can combine ANN search with standard SQL WHERE clauses. This enables metadata filtering natively without any special syntax — just write SQL.

-- Semantic search filtered to the 'database' category
-- and only recent documents
SELECT
    id,
    content,
    1 - (embedding <=> %s::vector) AS similarity
FROM documents
WHERE
    category = 'database'
    AND created_at > NOW() - INTERVAL '30 days'
ORDER BY embedding <=> %s::vector
LIMIT 5;

-- In Python with psycopg2:
# cur.execute(sql, (query_embedding, query_embedding))

Creating an HNSW Index for Speed

Without an index, pgvector does an exact scan of every row — fine for under 10,000 rows but slow at scale. Create an HNSW index for approximate nearest neighbor search. The m (connections per node) and ef_construction (build-time search width) parameters trade index size and build time for recall accuracy.

-- Create an HNSW index for cosine distance queries
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

-- At query time, control recall vs speed:
SET hnsw.ef_search = 40;  -- higher = better recall, slower

-- Verify the index is being used:
EXPLAIN SELECT * FROM documents
ORDER BY embedding <=> '[0.1]'::vector(1)
LIMIT 5;

IVFFlat Index: Alternative to HNSW

The IVFFlat index type clusters vectors into lists buckets and searches only the nearest probes buckets at query time. It builds faster than HNSW and uses less memory, but has slightly lower recall for the same speed.

Rule of thumb: use IVFFlat when you need faster index builds during frequent re-indexing; use HNSW for stable corpora that need maximum query speed.

-- IVFFlat index: good for large, infrequently updated corpora
-- lists ≈ sqrt(n) where n is the number of vectors
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);

-- At query time, probes controls recall vs speed:
SET ivfflat.probes = 10;  -- check 10 of 100 clusters

Full Python Query Example

Here is a complete Python function that takes a user query, embeds it, runs a pgvector similarity search with metadata filtering, and returns the top-k results as a list of dicts.

import psycopg2
from pgvector.psycopg2 import register_vector
from openai import OpenAI

conn = psycopg2.connect('postgresql://user:pass@localhost/mydb')
register_vector(conn)
client = OpenAI()

def semantic_search(query, category=None, top_k=5):
    resp = client.embeddings.create(model='text-embedding-3-small', input=query)
    q_vec = resp.data[0].embedding

    sql = '''
        SELECT content,
               1 - (embedding <=> %s::vector) AS similarity
        FROM documents
        {where}
        ORDER BY embedding <=> %s::vector
        LIMIT %s
    '''
    where = 'WHERE category = %s' if category else ''
    params = [q_vec, q_vec, top_k] if not category else [q_vec, category, q_vec, top_k]
    cur = conn.cursor()
    cur.execute(sql.format(where=where), params)
    return [{'text': r[0], 'score': r[1]} for r in cur.fetchall()]

pgvector vs Pinecone Trade-offs

Comparing pgvector and Pinecone:

  • pgvector: self-hosted, no extra cost, perfect SQL integration, scales to ~5M vectors well, requires DBA knowledge for tuning
  • Pinecone: fully managed, massive scale (billions of vectors), specialized filtering, more expensive, separate service to operate

Choose pgvector when you already run PostgreSQL and your corpus is under a few million documents. Choose Pinecone for massive scale or when avoiding ops burden is worth the cost.

Using pgvector with Supabase

Supabase is a hosted PostgreSQL service with pgvector pre-installed. It provides a Python client (supabase-py) and a REST API for vector queries, making it the easiest way to get a production pgvector setup without managing a database server yourself.

from supabase import create_client
import os

url = os.environ['SUPABASE_URL']
key = os.environ['SUPABASE_SERVICE_KEY']
supabase = create_client(url, key)

# Insert a document with embedding
supabase.table('documents').insert({
    'content': 'Supabase hosts PostgreSQL with pgvector.',
    'embedding': embedding   # list of 1536 floats
}).execute()

# Vector similarity search via RPC (Supabase edge function)
# result = supabase.rpc('match_documents', {'query_embedding': q_vec, 'match_count': 5}).execute()

Quick Check

Test your understanding of AI Engineering concepts from this lesson.

Lesson Recap

In this lesson you learned: pgvector adds a vector column type and cosine/Euclidean distance operators to PostgreSQL, HNSW indexes enable fast approximate nearest neighbor search at scale, and standard SQL WHERE clauses provide metadata filtering without any special syntax. Next up we compare all the major vector store options to help you choose the right one for your project.

Questions Fréquemment Posées

La leçon « pgvector : embeddings dans PostgreSQL » est-elle gratuite ?

Oui — le texte complet de « pgvector : embeddings dans PostgreSQL » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « pgvector : embeddings dans PostgreSQL » ?

Activez l’extension pgvector dans PostgreSQL, créez une table contenant une colonne vectorielle, insérez des embeddings et exécutez des requêtes de plus proches voisins à l’aide de l’opérateur de dis… Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?

Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « pgvector : embeddings dans PostgreSQL » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?

Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Pourquoi avez-vous besoin d’une base de données vectorielle
  2. Premiers pas avec Pinecone
  3. pgvector : embeddings dans PostgreSQL
  4. Choisir et évaluer les bases vectorielles
← Retour à AI Engineering Academy