BLOG

Tech Teardown 025|pg_vectorsearch : Nouvel index de recherche vectorielle officiel de Timescale, 100 millions de vecteurs en 6 millisecondes

Kael Zhang
Tech Teardownpg_vectorsearchPRISM 索引向量检索PostgreSQL
广告 · Advertisement

Le 13 octobre, Timescale (maintenant renommé Tiger Data) a ouvert le nouveau dépôt pg_vectorsearch sur GitHub, une extension de recherche ANN approximative pour PostgreSQL, dont le noyau est l’index PRISM développé en interne. Le lendemain, il a attiré beaucoup de discussions sur Hacker News, avec environ 200 likes et 50 commentaires. La popularité vient de trois facteurs : l’éditeur est l’ancienne équipe PostgreSQL qui développe TimescaleDB ; les chiffres donnés sur le blog officiel sont assez ambitieux (100 millions de vecteurs, 95% de recall, P50 en retard de 6 millisecondes, contre HNSW qui ne peut même pas établir d’index sur des machines du même niveau), et le choix d’une approche technique différente de celle de pgvector : pas d’index graphique, mais un index par partition. Mais mettons d’abord en avant la phrase la plus importante : l’état original de la fiche README indique « Meant for testing, not production », c’est-à-dire uniquement pour des tests, pas pour le production. Ce texte est divisé en six parties selon la tradition.

1. Qu’est-ce que c’est ?

pg_vectorsearch est une extension de recherche ANN performante pour PostgreSQL, fournissant une méthode d’accès à l’index appelée PRISM, dont le nom complet est Partitioned Routing Index for Similarity Matching. C’est un index de type IVF : les espaces vectoriels sont divisés en clusters selon les centres de gravité, et lors de la recherche, seules les quelques clusters ayant le plus de chances de réussir sont parcourus. C’est donc une approche de « scan par partition », contrairement à HNSW de pgvector qui utilise une approche « de déplacement sur l’image ». Les origines du design sont mentionnées dans le fichier AGENTS.md du dépôt : inspirées de ScaNN for AlloyDB de Google et SPANN de Microsoft, le format des vecteurs suit les spécifications de pgvector.

Il y a trois points importants à clarifier concernant son statut. Premièrement, c’est une production officielle de Timescale ; la même équipe a ouvert le dépôt pgvectorscale en 2024 (un index graphique DiskANN, dont l’auteur est mentionné par un commentateur précédent), et c’est leur deuxième tentative dans le domaine de la recherche vectorielle pour PostgreSQL. De plus, le blog officiel annonce clairement que pgvectorscale est passé en mode de maintenance, avec les ressources allouées à l’index nouveau. Deuxièmement, il est compatible avec pgvector et ne le remplace pas : les colonnes vectorielle/halfvec existantes ne doivent pas être réécrites ou copiées, il suffit d’établir l’index PRISM dessus, et les requêtes écrites avec les opérateurs de pgvector fonctionnent normalement. Il dispose également de deux types de vecteurs, vec32/vec16, ce qui permet son exécution indépendamment de pgvector. Troisièmement, c’est un alpha : il peut y avoir peu de possibilités de mise à jour entre les versions pré-publiées, et l’équipe recommande de se préparer à détruire et reconstruire l’extension et l’index.

Une phrase pour la décrire : C’est un index vectoriel par partition avec « zéro coût de migration » pour des essais, une approche ambitieuse, mais dont le niveau de maturité technique est encore bas.

2. Structure du dépôt

Première correction d’une petite erreur : la étiquette linguistique de GitHub indique que ce dépôt est en Rust, mais en réalité, il s’agit d’une extension purement en C. Dans le répertoire src, à la ligne 44006 se trouve un fichier .c ; il y a au total 62575 lignes de code .c et 13303 lignes de code .h dans tout le dépôt (voir les informations sur l’inspection du dépôt). La licence est une licence PostgreSQL légère, avec des exigences de compilation pour PostgreSQL 18+ ou plus, GCC 11 ou Clang 14, ainsi que le système de compilation Meson. Un lien optionnel est la acceleration CBLAS avec RaBitQ encoding.

La division des modules dans src correspond clairement aux différentes couches d’algorithmes : algo contient les algorithmes de clustering et de calcul des distances, index contient la construction et l’exploration des indices, quant concerne la quantification, pg est la couche de glue PostgreSQL, et standalone contient les moteurs indépendants. Dans algo, on trouve trois variantes de kmeans (lloyd, elkan, hamerly) ainsi que le clustering hiérarchique hkmeans ; le clustering est une étape essentielle pour la construction des indices, et chaque algorithme convient à différentes tailles de données. Quant contient deux implementations, rabitq et fastscan, chacune avec trois versions SIMD avx2, avx512 et neon. Dans index, les fichiers centroid_build, centroid_search, posting_build, posting_scan, posting_split, etc., séparent clairement les méthodes d’écriture et d’écriture des deux structures de données « arbre du centre de masse » et « table inversée ».

Une autre caractéristique intéressante est la configuration d’aide à la développement avec AI fournie par le dépôt : sous .claude/skills, il y a huit fichiers de compétences : build-feature, create-pr, git-workflow, profiling, release, review, security-review, testing, ainsi que AGENTS.md et CLAUDE.md, qui indiquent que le projet est développé selon le flux de travail Claude Code. L’auteur n’a pas précisé si le code a été généré par l’IA, mais il mentionne simplement que le dépôt contient cette configuration. Une extension C officielle place directement la configuration du flux de travail agent dans le dépôt ; cette pratique de développement est plus intéressante à observer que le volume de code.

III. Analyse des mécanismes

Le parcours de recherche de PRISM se déroule en cinq étapes : d’abord, on utilise l’arbre du centre de masse hiérarchique pour trouver les quelques clusters les plus proches (l’arbre est stocké dans le buffer cache), puis on explore les listes de postings de ces clusters pour trouver des candidats (I/O asynchrone), ensuite on utilise RaBitQ pour effectuer une filtration en deux étapes, et enfin on réorganise les vecteurs à précision complète dans la table de pile pour retracer les k proches voisins.

Analysons les trois piliers technologiques un par un. Le premier est le routage par partition : l’espace vectoriel est regroupé en clusters par kmeans, puis ces clusters sont organisés en un arbre du centre de masse superficiel. Lors de la recherche, le routage se fait de haut en bas, en touchant seulement une petite partie des partitions. Cela part du même concept que IVFFlat, mais la différence est que le routage arborescent accélère également le processus de « exploration des clusters ». Le blog mentionne également que PRISM implémente une technologie de débordement SOAR similaire à ScaNN : les vecteurs de bord sont stockés dans le deuxième cluster adjacent, échangeant un peu d’espace de stockage contre une meilleure recall.

Le deuxième point concerne RaBitQ quantification, présenté dans un article de SIGMOD 2024. Son avantage réside dans sa quantification binaire avec une limite d’erreur théorique. Chaque vecteur quantifié possède sa propre plage d’erreur ; lors de la recherche, on calcule d’abord la distance estimée, puis on élimine directement les vecteurs qui ne peuvent pas entrer dans le top k grâce à cette limite d’erreur. Seuls les rares candidats restants doivent être réexaminés en toute précision. La limite d’erreur est une garantie mathématique plutôt qu’une valeur empirique, ce qui constitue la différence fondamentale avec les solutions de quantification binaire classiques. La disposition des pages de la liste de publication a également été conçue spécifiquement pour le calcul de distance SIMD.

Le troisième point concerne l’intégration de SIMD et de l’ingénierie : le noyau de calcul de distance est implémenté selon trois ensembles d’instructions : AVX2, AVX512 et NEON. Le même code source est utilisé tant dans les extensions de PostgreSQL que dans le moteur standalone, ce qui facilite l’isolation des goulots d’étranglement de la base de données pour tester séparément les algorithmes. L’arbre du centre de masse dépend du cache de buffer partagé de PostgreSQL, tandis que les données vectorielles sont traitées via le système de pages disques. MVCC et la copie en flux sont inclus dans les objectifs de conception.

Les paramètres de configuration sont soigneusement simplifiés : sur le côté de la requête, il n’y a qu’un seul prism.nprobe (nombre de clusters à scanner). La valeur par défaut 0 signifie que la valeur est choisie automatiquement, avec une recall d’environ 95 %. En augmentant ou en diminuant cette valeur, on peut choisir entre une recall élevée et une vitesse plus rapide. En ce qui concerne les mises à jour, l’insertion consiste à ajouter les vecteurs dans la liste de publication touchée par la requête. La liste ne se divise pas automatiquement ; l’entreprise fournit la procédure de stockage prism_rebalance pour diviser manuellement les partitions trop grandes, ou bien effectuer une REINDEX pour reconstruire.

Quatrième point : Chiffres et vérification

Tous les chiffres des benchmarks suivants proviennent du blog officiel de Tiger Data (2026-10-13). Ce sont des données officielles, sans test indépendant par des tiers. Veuillez prendre en compte cette réduction lors de la validation.

Scénario majeur : 100 millions de vecteurs Cohere, comparaison entre deux instances AWS, r8i.4xlarge (16 vCPU/128 GiB de mémoire) et r8i.16xlarge (64 vCPU/512 GiB, 4 fois plus cher au prix du marché). PRISM met 1 heure 40 minutes pour créer une indexation sur une petite machine, avec une recall de 95% et un délai P50 de 6 millisecondes, et 21 millisecondes pour 99% de recall. HNSW ne peut pas être indexé sur cette machine ; il faut utiliser une grande machine (512 GiB) pour 42 heures, avec une recall de 95% et un délai de 8 millisecondes, mais 99% de recall ne permet pas d’atteindre un délai utilisable. Sur la même grande machine, PRISM met 49 minutes pour créer une indexation, avec un P50 de 4 millisecondes (95%) et 19 millisecondes (99%). L’entreprise a également essayé de transférer l’index HNSW créé sur la grande machine vers une petite machine pour effectuer des requêtes ; avec 95% de recall, chaque requête dépasse 1 seconde. La conclusion est que HNSW ne peut pas être utilisé à cette échelle sans une grande mémoire.

Petit scénario : Avec 1 million de vecteurs, PRISM atteint un taux de recall de 99% et une latence de 15 millisecondes sur un serveur c8g.medium avec 2 GiB de mémoire ; HNSW nécessite un deuxième volume de mémoire, avec une latence de 392 millisecondes, soit plus de 23 fois plus lent que la norme officielle. La création d’un index sur un serveur de 4 GiB prend environ 3 minutes pour PRISM, et 21,7 heures pour HNSW (le temps de construction ne permet pas d’intégrer les données dans la mémoire, ce qui provoque des fluctuations). Il convient également de mentionner que HNSW utilise 16-bit halfvec de pgvector, ce qui est déclaré par l’équipe comme le meilleur compromis testé pour HNSW.

Les faiblesses officielles sont mentionnées dans les Known issues du CHANGELOG : des écritures fréquentes peuvent entraîner des fluctuations dans le taux de recall, les partitions ne se redessinent pas automatiquement, nécessitant un prism_rebalance ou une REINDEX manuelle. L’équipe prévoit d’automatiser cela à l’avenir ; le nombre maximal de dimensions est de 1968 ; la suppression ne supprime que les entrées, sans récupérer l’espace des pages d’index ; les requêtes avec filtrage WHERE peuvent retourner moins de lignes que LIMIT, et la scanne ne reprend pas les candidats (c’est-à-dire que seuls les filtres ultérieurs sont effectués) ; lorsque LIMIT dépasse le budget work_mem, la trie est interrompue silencieusement. Les commentaires sur HN remettent également en question ce filtrage postérieur, certains demandant comment utiliser ce type d’index dans des scénarios de multi-tenant et de séparation des droits. L’équipe n’a pas répondu directement ; un commentateur a également remarqué le nombre maximal de dimensions lors de tests préliminaires.

V, Jugement

Trois points méritent attention.

Premièrement, le choix de la voie est plus important que les chiffres. HNSW a été la réponse standard pour la recherche vectorielle ces dernières années. ScaNN de Google, SPANN de Microsoft, et les nouveaux moteurs de turbopuffer ont tourné vers « partitionnement + quantification + scanning SIMD », car le scanning en ordre est plus favorable aux CPU modernes, tandis que la parcoursage des graphiques implique un accès aléatoire. PRISM est la dernière étape de cette voie dans l’écosystème PostgreSQL. Même si les chiffres officiels sont réduits, l’avantage structurel que « les machines à petite mémoire peuvent gérer de grands index » n’est pas possible avec les index de graphiques : les graphiques HNSW doivent être principalement hébergés en mémoire, tandis que la quantification de la liste de postings de PRISM peut être stockée sur le disque pour un scanage selon besoin.

Deuxièmement, la compatibilité avec pgvector est une stratégie intelligente. En ne forçant pas les utilisateurs à migrer les tables, les requêtes ou les opérateurs, il suffit d’ajouter un index sur les colonnes existantes pour effectuer des tests comparatifs, ce qui réduit considérablement les coûts de test. Cela répond également à la question « va-t-il remplacer pgvector » : non, il ressemble plutôt à un backend d’index intégrable dans l’écosystème pgvector. Certains ont demandé pourquoi il n’y avait pas directement une PR pour pgvector, mais l’équipe n’a pas répondu. D’après le passage de pgvectorscale au mode de maintenance, Timescale souhaite un produit indépendant contrôlant son propre rythme d’itération.

Troisièmement, les faiblesses de l’alpha sont réelles, et ce n’est pas simplement une modestie liée au numéro de version. Pour les SaaS multi-tenant, le fait que seul le filtrage postérieur soit utilisé signifie « d’abord scanner une multitude de candidats qui ne sont pas de ce tenant, puis les jeter », ce qui réduit l’efficacité avec des conditions de filtrage plus strictes. C’est un problème reconnu dans le CHANGELOG, soulevé par les commentaires et encore non résolu par l’équipe ; le nombre maximal de 1968 dimensions exclut certains modèles à haute dimensionnalité ; dans les scénarios de churn, il faut manuellement surveiller le rebalance, ce qui crée une charge opérationnelle réelle. Tout cela, ajouté au fait que « les versions pré-publiées pourraient ne pas être facilement améliorées », constitue une liste complète de points à considérer avant de juger le produit.

Un instant de observation technique : Le dépôt officiel C Extension intègre une configuration complète du flux de travail Claude Code (huit fichiers de compétences plus AGENTS.md), ce qui montre que le développement assisté par l’IA a déjà atteint des domaines traditionnellement les plus conservateurs, comme le noyau de la base de données. La qualité du code est finalement déterminée par les résultats des tests, mais l’action de l’intégrer dans le dépôt en soi vaut la peine d’être examinée par chaque équipe travaillant sur les infrastructures.

VI. Qui peut l’utiliser et comment

Cela convient aux équipes dont la taille des vecteurs se situe entre dix millions et cent millions, qui sont confrontées à une charge de mémoire importante due à HNSW et souhaitent rester dans PostgreSQL (besoin de joindre des données commerciales, de mettre à jour en une seule transaction), et qui peuvent accepter les risques associés à alpha. Les scénarios où pgvector est déjà utilisé sont les plus pratiques : après CREATE EXTENSION pg_vectorsearch, on crée directement CREATE INDEX… USING prism sur les colonnes vectorielles existantes. On exécute EXPLAIN pour vérifier que le plan de requête utilise le nouveau index, puis on compare les deux indices pendant un certain temps avant de supprimer HNSW si satisfait. La relation entre les opérateurs est vector_l2_ops remplacée par vec32_l2_ops, halfvec par vec16, et les trois distances L2, produit scalaire et cosinus sont toutes supportées.

L’optimisation se fait en un seul clic : prism.nprobe cible automatiquement environ 95% de recall par défaut. Pour plus de recall, augmentez la valeur ; pour moins de retard, diminuez-la. Pour les bases de données qui écrivent fréquemment, planifiez prism_rebalance dans le plan d’opération ou effectuez des REINDEX régulièrement ; l’équipe officielle ne recommande pas d’établir des indices sur des tables vides avant de charger des données. Dans les scénarios où beaucoup de données sont supprimées, notez que l’espace indexé n’est pas récupéré automatiquement.

La seule recommandation pour les environnements de production est : attendre son version beta. Le plan officiel inclut un rebalancing automatique, des recherches filtrables en flux continu (WHERE et ORDER BY produisant continuellement des candidats), ainsi que des tests renforcés de la copie physique et du restauration des sauvegardes, ce qui correspond précisément aux points les plus difficiles à surmonter actuellement. La meilleure approche maintenant est de tester avec des données réelles dans l’environnement de test, de faire remonter les résultats sur GitHub. Selon le blog officiel, « si vos résultats ne correspondent pas aux nôtres, lancez une issue, nous verrons ce que nous pouvons faire ».

Pour ceux qui ne comptent pas l’utiliser, ce dépôt vaut également la peine d’être lu : les implementations de trois variantes de kmeans dans src/algo, le codage RaBitQ avec trois noyaux SIMD dans quant, ainsi que les normes complètes de développement C extension contenues dans AGENTS.md, constituent tous des manuels de référence pour le développement du noyau de la base de données.

Source d’information

  • Repos et documents : README, CHANGELOG (0.1.0, 2026-10-13) de github.com/timescale/pg_vectorsearch, AGENTS.md, structure des répertoires src et nombre de lignes de code (visualisation des repos de 10 à 15, statistiques avec find+wc).
  • Tous les chiffres pour les benchmarks (100 millions/1 million vecteurs, délai, temps d’indexation, spécifications matérielles, baseline halfvec) : Blog officiel de Tiger Data « Announcing pg_vectorsearch » (tigerdata.com, 2026-10-13). Tous les éléments sont d’après les informations officielles, le texte est marqué comme tel.
  • Problèmes connus (churn drift, limite supérieure de 1968 dimensions, filtrage postérieur, non-récupération de l’espace, truncation de work_mem) : CHANGELOG 0.1.0 Known issues. Texte original.
  • Discussions sur HN (environ 200▲/50 commentaires, questions sur le filtrage postérieur, mesures pratiques des limites de dimensions, auteur de pgvectorscale présent) : Historique et pool de commentaires sur HN, ajouté le 2026-10-14. Les commentaires sont traités comme des récits.
  • « Inspiré par ScaNN/SPANN » « Prédécesseurs et mode de maintenance de pgvectorscale » : Description de AGENTS.md et blog officiel.
  • Le nombre d’étoiles n’est pas donné avec précision, le texte est traité selon la classification « Nouvellement publié/Ouvert à quelques jours ».
广告 · Advertisement

Questions fréquentes

Qu'est-ce que pg_vectorsearch ?

pg_vectorsearch est une extension ANN (Approximate Nearest Neighbor) pour PostgreSQL, développée par TimescaleDB, qui utilise l'index PRISM et la quantification RaBitQ pour améliorer les performances de recherche vectorielle.

Quels sont les avantages de pg_vectorsearch ?

pg_vectorsearch permet de rechercher 100 millions de vecteurs en 6 millisecondes avec un rappel de 95 %, ce qui est plus rapide que HNSW et consomme environ un quart de la mémoire.

Est-ce que pg_vectorsearch est prêt pour une utilisation en production ?

Non, selon le README original, pg_vectorsearch est destiné uniquement aux tests et ne doit pas être utilisé en production.