138M文檔,18分鐘建完索引,查詢快6.5倍——這不是Elasticsearch的發(fā)布會,是Postgres的擴展在干的事。
Tiger Data(TimescaleDB的團隊)昨天把pg_textsearch 1.0甩了出來。一個原生BM25搜索引擎,直接長在Postgres的存儲層上,不用外掛,不用同步,不用半夜爬起來修數(shù)據(jù)不一致。
用過Postgres內置ts_rank的人,都知道這套組合拳有多憋屈。語料庫一漲,排名質量就塌。沒有逆文檔頻率(IDF),"的"和"Postgres"權重一樣。沒有詞頻飽和,一篇把"數(shù)據(jù)庫"復讀50次的垃圾文,能碾壓只提一次的技術深度文。更絕的是top-k查詢——得把所有匹配行掃一遍才能算分。
于是大家被迫搞雙系統(tǒng):Postgres存數(shù)據(jù),Elasticsearch或Typesense扛搜索。數(shù)據(jù)同步、集群運維、一致性對賬,三件套加班套餐。
pg_textsearch想拆掉這套架構。純C手寫,基于Postgres原生存儲層,BM25算法完整實現(xiàn)。建索引就一行:
CREATE INDEX ON articles USING bm25(content) WITH (text_config = 'english');
查詢用<@>操作符返BM25分數(shù)。分數(shù)取負,所以Postgres默認升序ORDER BY直接出最相關結果。索引存在標準Postgres頁里,走緩沖緩存,進WAL日志,pg_dump能備份,流復制能同步——和正常表一個待遇。
從內存玩具到生產(chǎn)級:5個月的重寫
2024年10月的預覽版還像個Demo:倒排索引全放共享內存,重啟重建。180+提交之后,架構徹底換血。
磁盤化分段結構替換了內存-only設計。Block-Max WAND算法加WAND優(yōu)化,讓top-k查詢不用全表掃。倒排列表壓縮用SIMD加速解碼,索引體積砍了41%。并行建索引,138M文檔17分多鐘跑完。
性能數(shù)字和ParadeDB/Tantivy正面剛:2-4詞查詢快2.4到6.5倍,并發(fā)吞吐高8.7倍。這是Tiger Data自己跑的分,但他們也老實交代了ParadeDB更快場景——長查詢、復雜布爾,Tantivy的優(yōu)化更成熟。
「我們選擇在Postgres頁內實現(xiàn),而不是外部存儲,」團隊在技術博客里寫,「這意味著你得到的是事務一致性、崩潰恢復、備份工具鏈的完整繼承,代價是某些極端場景下不如專用引擎靈活。」
BM25為什么難搞:三個數(shù)學細節(jié)
ts_rank和BM25的差距,本質是信息檢索理論的代差。
逆文檔頻率(IDF)解決的是"這個詞有多特別"。在1000萬文檔里出現(xiàn)100次的詞,比出現(xiàn)500萬次的詞,權重該高兩個數(shù)量級。ts_rank沒有這茬。
詞頻飽和解決的是"復讀機問題"。BM25的公式里,詞頻增長對分數(shù)的貢獻是邊際遞減的——第2次提到"數(shù)據(jù)庫"加分多,第50次幾乎不加。ts_rank線性累加,催生SEO垃圾文。
字段長度歸一化解決的是"篇幅偏見"。200字的短文檔和2萬字的百科全書,同樣提到3次關鍵詞,前者應該更聚焦。BM25算這個,ts_rank不算。
pg_textsearch把這三件套全塞進Postgres的索引AM(訪問方法)接口。<@>操作符背后,是完整的BM25公式計算,包括可調節(jié)的k1和b參數(shù)。
架構解剖:為什么不搞外部存儲
ParadeDB和Tantivy的路子是:用Rust寫高性能引擎,通過Postgres的FDW(外部數(shù)據(jù)包裝器)或自定義協(xié)議橋接。查詢時要跨進程通信,數(shù)據(jù)要兩份存儲。
pg_textsearch賭的是另一條路:完全內嵌。
索引結構用Postgres的頁(8KB默認)存儲,分段(segment)管理。每個段是獨立的倒排索引單元,支持后臺合并。WAL日志記錄所有變更,崩潰恢復走標準流程。緩沖緩存自動管理熱數(shù)據(jù),不用自己搞內存池。
代價是代碼復雜度。Postgres的AM接口設計于90年代,給B-tree用的。倒排索引的隨機訪問模式、壓縮編碼、SIMD解碼,都要在接口縫隙里塞進去。Tiger Data團隊重寫了五個月的存儲層,才把預覽版的內存結構改成磁盤持久化。
Block-Max WAND是查詢層的關鍵優(yōu)化。傳統(tǒng)BM25要對所有匹配文檔算分排序,WAND用塊級上界(block-level upper bound)剪掉不可能進top-k的分支。138M文檔的語料庫,查"database ranking"兩個詞,可能只掃幾千個塊就停。
誰該用,誰再等等
現(xiàn)階段的限制,團隊列得清楚。
短語查詢和鄰近搜索還沒做,tsquery的<->操作符不支持。多字段加權(標題權重2倍,正文權重1倍)需要建多個索引手動合并。實時更新是行級觸發(fā)器實現(xiàn),高頻寫入場景有開銷。最要命的可能是:還沒和Postgres的并行查詢執(zhí)行器深度整合,某些plan會選錯。
但場景對口的人,現(xiàn)在就能上。內容站點、文檔知識庫、電商商品搜索——數(shù)據(jù)已經(jīng)在Postgres里,查詢模式是2-4個關鍵詞的 relevance ranking,不想養(yǎng)第二個集群。
Tiger Cloud客戶已經(jīng)能用托管版。開源版在GitHub,Apache 2.0協(xié)議,自己編譯安裝。
一個細節(jié):團隊特意測了pg_dump和pg_restore的兼容性。138M文檔的索引,備份恢復走標準流程,不需要額外工具。這對運維來說是真金白銀的省心——不用寫自定義備份腳本,不用教新人"搜索集群的恢復流程不一樣"。
Postgres生態(tài)的搜索方案,現(xiàn)在有三條路線并行。Elasticsearch側car是成熟但沉重的老大哥。ParadeDB是性能激進的外部引擎派。pg_textsearch押的是"原生內嵌"——犧牲部分極限性能,換架構簡潔和操作統(tǒng)一。
你的數(shù)據(jù),現(xiàn)在有幾份拷貝在跑?
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.