pgvector vs Qdrant : rappel et latence de la recherche filtrée par ACL
Mesurer la perte de rappel et la latence d'une recherche vectorielle filtrée par dossier_id (10 %, 30 %, 100 % de portée) avec pgvector HNSW (sans et avec iterative_scan, RLS) et Qdrant (payload is_tenant, JWT payload).
- Statut du test
- À tester
- Priorité
- Haute
- Prévu pour
- Octobre 2026
- Hypothèse
- Avec hnsw.iterative_scan activé, pgvector conserve au moins 90 % du rappel non filtré pour un utilisateur ayant accès à 10 % des dossiers, à une latence inférieure à 200 ms ; Qdrant y parvient sans réglage grâce au filtrage intégré à HNSW. Dans les deux cas, la barrière moteur (RLS, JWT payload) ne renvoie aucun point hors portée.
- Procédure
- Corpus synthétique de 1 million de chunks (1 024 dims) répartis sur 200 dossiers. 100 requêtes. Mesurer recall@20 (contre une recherche exacte) et latence p95 pour des portées de 10 %, 30 %, 100 % : pgvector HNSW défaut ; pgvector + iterative_scan relaxed_order ; pgvector + index partiels ; pgvector + RLS active ; pgvectorscale ; Qdrant collection unique payload is_tenant ; Qdrant avec JWT payload. Vérifier zéro point hors portée avec la barrière moteur seule.
Pourquoi
C'est le test qui tranche Q-004. pgvector documente que « With approximate indexes, filtering is applied after the index is scanned. If a condition matches 10% of rows, with HNSW and the default hnsw.ef_search of 40, only 4 rows will match on average », et propose depuis 0.8.0 les « iterative index scans » 1. Qdrant intègre le filtre payload à HNSW et regroupe les points par tenant avec is_tenant 3. Le filtre ACL est précisément ce cas : un avocat voit une fraction des dossiers.
Protocole
- Générer 1 million de chunks synthétiques (texte aléatoire vectorisé par le modèle retenu, ou vecteurs synthétiques) sur 200 dossiers de tailles inégales.
- Calculer la vérité terrain par recherche exacte (scan complet) pour 100 requêtes et 3 portées (10 %, 30 %, 100 % des dossiers).
- pgvector : HNSW
m=16, ef_construction=64;ef_search40 puis 100 ;hnsw.iterative_scan = off | relaxed_order | strict_order; index B-tree surdossier_id; variante index partiels ; variante RLS active avec rôle non superuser etSET LOCAL app.user_id2 ; lire le plan d'exécution pour vérifier l'ordre filtre / distance. - pgvectorscale : même jeu avec StreamingDiskANN et filtre par labels 5.
- Qdrant : collection unique, payload
dossier_idindexéis_tenant: true; variantepayload_m: 16, m: 0; variante JWT avec claimpayload4. - Mesurer recall@20 et latence p95, mémoire résidente, temps de construction de l'index.
- Barrière seule : requêtes sans filtre applicatif, avec RLS ou JWT seulement : zéro point hors portée attendu.
Critères
Rappel filtré à 10 % supérieur ou égal à 90 % du rappel non filtré ; latence p95 inférieure à 200 ms ; zéro point hors portée avec la barrière moteur seule. Si pgvector satisfait les trois, il est retenu (une seule base à exploiter) ; sinon Qdrant.
Résultat
À venir.
Sources
- 1pgvector — README (filtrage, HNSW, iterative scan 0.8.0)GitHubFiabilité hautepgvector · publié v0.8.6 (README) ; 0.8.0 annoncé sur postgresql.org · consulté le 16 sept. 2026 · fiche source
- 2PostgreSQL — Row Security Policies (RLS)Documentation officielleFiabilité hautePostgreSQL · publié documentation courante · consulté le 16 sept. 2026 · fiche source
- 3Qdrant — Multitenancy (payload partitioning, is_tenant)Documentation officielleFiabilité hauteQdrant · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
- 4Qdrant — Security (API key, TLS, JWT avec claim payload)Documentation officielleFiabilité hauteQdrant · publié lu le 16/09/2026 ; RBAC JWT introduit en 1.9.0 (blog du 24/04/2024) · consulté le 16 sept. 2026 · fiche source
- 5pgvectorscale — README (StreamingDiskANN, filtered search)GitHubFiabilité moyenneTimescale · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source