17年的舊文,最近因為SageDB論文而重讀。
文章主要思路是通過學習key的順序、結構等來預測record在位置、存在與否等。效果方面,據稱部分場景下,相對b-tree可以優化70%的內存占用。
最大價值其實在於使用ML來優化(索引)系統這個新的方向。
Range Index
審視下btree查找完成的功能:輸入一個key,每次選出一個可能的范圍(分支節點),直到最后命中(葉子節點)。這其實跟ML中模型類似。

換句話說,若能估算出數據的累積分布(記作F),那么查詢key所在位置,也可以看成是 pos = F(key) * N 這樣一個過程。
基於此,文章首先嘗試了朴素的方案:使用tf訓練並運行一個2層全連接的神經網絡,每層32個單元,使用ReLU作為激發函數。
然而這個方案運行效果很差,單次查找耗時比btree高了2個數量級。原因是多方面的:
- TF並不針對小數據集優化
- 單一的神經網絡在最后的精細部分(last mile),需要花費大量的計算與存儲資源
- btree的設計考量了內存優化等,而朴素方案顯然還較為粗糙(全連接層)
The RM-Index

針對上文朴素方案的問題,文章進行了一系列的優化。
首先不再使用TF進行推斷查找,而是開發發了一個叫LIF的框架,從TF模型中提取權重參數,直接生成專為小數據集優化的高效C++代碼。
其次,使用RMI遞歸(而非單一)模型,在逐步縮小key的范圍。由於每次問題被分解到小范圍內進行,資源消耗得到改善的同時,模型的精度可以更好提升。RMI每層的輸出是下一層的輸入,有利於使用TPU/GPU進行優化。RMI中可以在不同的stage混合使用btree在內的不同類型模型來達到最佳效果,所以理論上不會比單純的btree差。這個思路很ML,一個模型接一個模型:)
並且,由於模型實際上已經預測出key的位置(position),而不僅僅是范圍(range),本文使用了兩種新的查找算法(MBS、BQS)利用該信息來更高效地進行查找。
一連串的優化之后,模型的訓練和運行有了明顯的優化。其中,訓練過程使用sgd只需要一次或少量的訪問就可以。2億條記錄能在秒級完成。
對於整型數據集,相同內存占用時下,RMI經常能較btree有數倍性能提升。或者說性能相同時,內存占用會有數量級的優化。見下圖:

在盡量公平相似的場景下,跟其他相關方案(FAST等)比也有明顯優化:

在字符串場景下,優化場景不明顯,原因可能在於字符串比較太耗時,model執行時間過長等。后者用TPU/GPU可能會有優化空間。
Point Index
point idx(hash索引)的優化基礎在於,典型的數據沖突可能會有33%(如生日)。然而實際減少沖突和運行效果取決於兩個主要方面:
- 數據本身的分布情況。比如均勻分布場景下,learned idx不會比普通的隨機hash函數好多少;
- 其他payload等
從文章的數據集來說,還是有效果的:

Existence Index
存在性的索引,本文優化方面主要在於內存占用:10億記錄典型bloom filter需要1.76GB,如果要FPR為0.01%,則需要2.23GB。
前邊在索引需要學習數據分布,而存在性索引,需要讓合法的key相關,非法的key相關,而合法key與非法key間不相關。這其實就很像分類問題了。
另一方面,由於ML的特別,FPR下降時,FNR通常會上升。這跟bloom filter要求的FPR盡量小,FNR為0有沖突。解決方案是,在模型判斷為false時,另行使用一個overflow bloom filter進行判斷。由於bloom filter的大小於數據集相關,因為后接的bloom filter大小於FNR(即false部分相關),這要遠小於傳統方案中的大小。

需要注意的是,該文章只研究了查詢存在一定規律的場景,並在此這上建立模型。這在實際使用時要視業務場景而定。
在符合條件的情況下,1.7M條URL, 1. FPR 0.5%,FNR 55%時,2.04MB->1.31MB,減少36% 2. FPR 0.1%,FNR 76%時,3.06MB->2.59MB,減少15%。

Conclusion and Future Work
文章研究的是單一維度索引,如果能支持多維索引,對現實系統將會有更多幫助。
文章提到其價值時指出目前的索引是state-of-the-arts狀態。有意思的是,ML又何嘗不是呢?:)
