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.
-- 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.
À lire ensuite
Toute la rubrique DonnéesDonnées
Files d'attente dans PostgreSQL : jusqu'où
Une table et SKIP LOCKED font une file d'attente sérieuse, jusqu'au jour où une transaction longue ailleurs dans la base la met à genoux. Le mécanisme, les deux patrons de consommation, et les signaux qui disent qu'il est temps d'en sortir.
6 minMembres
Données
Analytique embarquée dans un SaaS
Où faire tourner les tableaux de bord que voient vos clients : sur la base transactionnelle, une replica ou un magasin séparé, avec quelle fraîcheur annoncée et quelle isolation entre tenants.
6 minMembres
Données
CDC : le slot de réplication qui remplit votre disque
Un slot de réplication logique est une promesse de ne rien supprimer tant que le consommateur n'a pas confirmé. Les quatre façons dont cette promesse remplit le disque du primaire avec Debezium, et les garde-fous à poser avant la mise en production.
7 minMembres