Hacker News ★ 94 4 min

RIP, vector database

🔗 https://turbopuffer.com/blog/rip-vector-database

📌 turbopuffer拆掉ANN主索引,重構v3儲存架構

TL;DR:turbopuffer要把向量索引從「主索引」降為「次要索引」,目標是讓text、regex、SQL查詢全面提速。

一個撐起過100B+向量、服務Cursor和Notion的向量資料庫,現在主動承認自己的核心設計已經「撐到頭了」,這本身就值得工程師停下來看看發生了什麼事。

🤔 ANN主索引拖累了非向量查詢

turbopuffer從v1開始就是一個serverless向量資料庫,用物件儲存(object storage)當真相來源,搭配分層NVMe SSD/記憶體快取拿到效能,這套取捨已經被Cursor、Notion等早期客戶驗證過。但這篇文章指出,這套架構在往text search、regex search、attribute filtering、aggregation等非向量查詢擴張時,開始遇到三個結構性問題:儲存放大(多向量表示時,文件內容必須在每個向量底下重複儲存一次)、寫入放大(SPFresh在重新平衡向量分群時,會連帶搬動整份文件內容及其所有倒排索引)、以及向量化受限(ANN索引的cluster大小落在100-200筆,但像DuckDB用2048筆、ClickHouse用到約6.5萬筆的批次大小才能發揮現代向量化查詢引擎的效能)。

🧩 從C0L1位址到讓ANN變成「只是另一個索引」

turbopuffer v1把每個向量分群(cluster)再分群成樹狀結構(源自SPANN,後改用支援增量索引的SPFresh),每個向量都有一個由ClusterId與LocalId組成的「ANN位址」(如C0L1),所有東西都用這個位址當主鍵儲存——這就是文中所說「ANN索引是主索引」的意思。v2在這個基礎上加入了attribute filtering(把屬性值映射到ANN位址的倒排索引)與BM25全文搜尋(儲存term count、document length等BM25評分所需的metadata)。v3要做的改變很直接:不再用ANN位址當主鍵,讓ANN變成眾多次要索引之一。

📊 FTS重構的前例:索引縮小10倍,查詢快20倍

文章提到一個已經發生過的案例作為佐證:FTS v1把posting list依照ANN cluster邊界切分,每個block平均只有約1.5筆posting;FTS v2把posting重新組織成固定約256筆的block後,索引縮小了10倍,查詢最高快了20倍。這個結果之所以可能,是因為posting list被獨立出來存放、只是指向文件,不必再跟著cluster的版面走。turbopuffer目前的規模是單索引撐住100B+向量、200ms p99延遲、1k+ QPS,整體引擎則承載1T+文件、10M+寫入/秒、25k+查詢/秒;v3目前的進度是「100% CI通過」,團隊的下一步是先追上、再超越現有效能水準。

💡 分離「索引結構」與「文件儲存」才是通用解法

FTS v2的經驗等於是turbopuffer團隊的一次小規模驗證:只要把某種查詢型態的資料結構,從「必須跟著ANN cluster走」的限制中解放出來,就能拿到可觀的效能提升。v3要做的,就是把這個原則從FTS一個查詢型態,推廣到aggregation、GROUP BY等所有查詢計畫上。

⚠️ 效能調校才剛開始,風險在於動到已經調到極致的ANN效能

文章也坦承,目前的ANN索引設計已經被打磨到「真的很好用」的程度,任何大改動都有可能讓ANN搜尋效能出現退步,這也是為什麼他們強調接下來要先做到效能持平(parity),再往上追求超越。

🎯 實務啟示

如果你的系統同時需要向量搜尋、全文搜尋、屬性過濾甚至SQL聚合,這篇文章提供了一個很具體的反例:單一索引結構(即便是設計得很好的ANN索引)如果被當成所有查詢計畫的主索引,長期會在儲存放大、寫入放大與向量化批次大小上處處受限。評估向量資料庫時,值得多問一句:它的非向量查詢是建立在獨立的儲存結構上,還是被迫掛在向量索引的版面之下。

🔗 來源

#VectorDatabase #turbopuffer #SearchEngine #ANN #FullTextSearch #DatabaseArchitecture #ObjectStorage #SystemsDesign #SPFresh #QueryEngine

原始資料 Hacker News · 收集於 2026-10-02
來源原標題
RIP, vector database
作者
razin
原始標籤
hackernews
來源訊號
HN points 374 HN 留言 105
原始連結
https://turbopuffer.com/blog/rip-vector-database

摘要原文

We are changing turbopuffer's storage architecture to take search to the next level. turbopuffer v3 changes how documents and indexes are laid out, written, compacted, and queried in turbopuffer. It will allow us to make search faster in every respect — including text, regex, and vector search — but it also lays the foundation to move many more SQL queries to turbopuffer and make them fast. turbopuffer launched as a serverless vector database (v1) , highly specialized to the task of serving extremely cheap and reasonably fast vector searches. Object storage as the source of truth gave the economics, and tiered NVMe SSD/memory caches gave the performance. The value of these particular tradeoffs was validated by our earliest customers, including Cursor and Notion. turbopuffer evolved to have very strong text and regex search (v2), and is being used for many non-search use cases, like Linear's syncing engine . The query engine has evolved along the way to support all of these query plans, but the storage architecture has remained largely unchanged: the ANN vector index was and still is the primary index around which all other indexes and query plans revolve. This design has constrained several query plans, like GROUP BY and aggregations. We've pushed the vector-primary architecture as far as we can, and it's time to move on. We're in the process of moving to a new primary index, and making ANN "just another" secondary index. We thought it might be fun to open up the doors and let you follow along. For this first update, we'll set the stage with why we're doing this in the first place. Walk with me on a short journey from tpuf v1 to today. In the first version of turbopuffer, documents consisted of nothing but an ID and a vector. The prevailing wisdom at the time was graph-based vector indexes, but a hierarchical clustering index plays better with object storage. We started with SPANN , and eventually migrated to SPFresh to support incremental indexing. Vectors are clustered into groups, whose centroids are clustered in turn, repeated to form a tree with a single root. We implemented this on top of a storage layer presenting as a key-value map, with sorted and unique keys. Each cluster is given a ClusterId , and vectors within each cluster are given a dense LocalId . As you can see above, everything is keyed by ClusterId and LocalId (e.g. C0L1 ), which together we call the ANN address . This is what we mean when we say the ANN index is the primary index. Two new query plans marked the informal transition from turbopuffer v1 → v2: attribute filtering and full-text search. Naturally, customers wanted to be able to add attribute values and filter vector searches on them. To make filtering fast and high-recall , we modeled these as an inverted index that maps an attribute value to the ANN address of the documents that contain it. For projections ( include_attributes ), we also stored the document attributes alongside the ID and the vector. BM25 full-text search was another obvious and much-demanded query plan. Similar to attribute search, full-text search works by first finding the documents that have the query term present (commonly called "postings"). For an FTS index, we also include the (term count, document length) metadata necessary for BM25 scoring: Over time, we've shipped several other index structures and query engines: aggregations , regex search , fuzzy matching , sparse vector search , and attribute ordering — all built around the same vector-primary storage layout. The ANN primary index has largely remained intact until today for one simple reason: it works really, really well for ANN search on object storage. On top of this architecture, we've pushed vector search to single indexes of 100B+ vectors serving 200 ms p99 reads at 1k+ QPS . Any significant change here risks introducing regressions in ANN performance. However, this layout holds us back from being state-of-the-art for the non-vector query shapes we support, in three main ways: storage amplification, write amplification, and limited vectorization. As described above, turbopuffer currently puts the full contents of each document under its ANN address. When there is only one vector, the non-vector data is stored alongside the vector only once. However, for multi-vector representations of a document, such as document nesting or late interaction, this means we have to duplicate the contents for each vector. This is the reason for some of our more unfortunate limits . Any time a document is inserted, updated, or deleted, SPFresh may rebalance the vectors to ensure they remain well clustered (otherwise recall may suffer). Because everything in a document is stored keyed by the ANN address of the document's vector, this rebalancing cascades to moving the full document contents, as well as any inverted (attribute and FTS) indexes that reference it. Updating just one vector can move hundreds of attributes and their indexes. This write amplification is large enough that our efforts to tune indexing throughput have started to hit diminishing returns. Modern query engines are vectorized : they run tight loops over blocks of values, which amortizes fixed per-block costs, compresses better, keeps the CPU pipeline full, and unlocks SIMD. DuckDB, for example, works in batches of 2,048 rows, ClickHouse up to ~65k, Lucene's posting blocks are 256 docs, and our ANN index works best with clusters of around 100–200 documents. Every query plan has an optimal block size, but today they are all constrained by the ANN primary index. A plan that wants blocks of thousands of documents to keep the CPU saturated is still stuck at 100–200. We've already documented how much this matters in turbopuffer. Our first version of full-text search partitioned posting lists along ANN cluster boundaries, and the median block held just ~1.5 postings. FTS v2 reworked postings into fixed blocks of ~256, and the index got 10x smaller and queries got up to 20x faster. Posting lists could do that because they're stored separately and point at documents, so their layout doesn't have to follow the clusters. Aggregations and other scans read the documents themselves, and those are stored one block per cluster. As long as the ANN address is the primary key, their block size is constrained to the cluster size, even if they'd prefer something larger. The solution to these problems is simple: don't key on the ANN address. That is precisely the change turbopuffer v3 makes. As you can imagine, it is not a trivial change. v3 is a new foundation that will unlock significant performance improvement on all query plans, and we hit a major milestone earlier this month: 100% of CI passes on turbopuffer v3. We started by focusing on correctness. Now we will make it correct and fast. Watching benchmark numbers go down is great fun, so we wanted to get you in at day zero of perf grinding. We will share the benchmarks in public over the coming weeks, as we work toward (and beyond) performance parity before rolling out v3 to production. turbopuffer is a fast search engine that hosts 1T+ documents, handles 10M+ writes/s , and serves 25k+ queries/s . We are ready for far more. We hope you'll trust us with your queries. (374 points, 105 comments on Hacker News)

由 claude-code/sonnet 自動生成