Aller au contenu
Recherche vectorielle dans PostgreSQL : limites à mesurerLecture : 0 %

Recherche vectorielle dans PostgreSQL : limites à mesurer

Les limites de pgvector qui décident s'il vous suffit (rappel de l'index, filtrage par tenant, mémoire) et la façon de les mesurer sur vos propres données avant de choisir une base dédiée.

Par Elias Varen6 min de lectureMembres

Avec pgvector, une recherche par similarité est un ORDER BY de plus. Les vecteurs vivent à côté des lignes qu'ils décrivent, dans la même transaction, derrière les mêmes droits, dans la même sauvegarde. Pour un SaaS qui a déjà PostgreSQL, c'est le bon point de départ, et pour beaucoup c'est aussi le point d'arrivée.

Les limites existent, et aucune ne se manifeste par une erreur. Un index approximatif qui rate la moitié des bons résultats renvoie quand même dix lignes. Une requête filtrée qui n'en renvoie que trois sur dix ne lève aucune exception. Un index qui ne tient plus en mémoire répond, simplement dix fois plus lentement. Chacune de ces limites se mesure en une heure sur vos données, et aucune ne se devine.

Ce que l'index HNSW ne retrouve pas

Sans index, PostgreSQL calcule la distance entre la requête et chaque vecteur, trie, et renvoie les vrais plus proches voisins. C'est exact et linéaire. Un index HNSW remplace ce parcours par une navigation dans un graphe ; il part d'un point d'entrée, suit les voisins les plus prometteurs et s'arrête après avoir examiné un nombre borné de candidats. Il est rapide parce qu'il ne regarde pas tout, et il se trompe pour la même raison.

Le rappel est la proportion des vrais voisins que l'index retrouve. Il dépend de la construction du graphe (m, ef_construction), de la largeur de recherche (hnsw.ef_search) et de vos données. Le seul chiffre qui vaille est celui que vous mesurez, et PostgreSQL fournit la vérité terrain gratuitement, puisqu'il suffit d'interdire l'index.

SQL
-- Vérité terrain : parcours exact
BEGIN;
SET LOCAL enable_indexscan = off;
SELECT id FROM passage ORDER BY embedding <=> $1 LIMIT 10;
COMMIT;

-- Résultat de l'index
BEGIN;
SET LOCAL hnsw.ef_search = 40;
SELECT id FROM passage ORDER BY embedding <=> $1 LIMIT 10;
COMMIT;

On rejoue les deux sur une centaine de requêtes réelles, on compte l'intersection des identifiants et on divise par dix. Puis on recommence avec ef_search à 100, puis 200, en notant la latence. On obtient ainsi la courbe qui décide du réglage, c'est-à-dire ce que chaque point de rappel coûte en millisecondes.

Recherche vectorielle dans PostgreSQL : limites à mesurer · Deepstack