lucene倒排索引--fst和SkipList的結合
1. 使用FST儲存詞典,FST可以實現快速的Seek,這種結構在當查詢可以表達成自動機時(PrefixQuery、FuzzyQuery、RegexpQuery等)效率很高。(可以理解成自動機取交集)
此種場景主要用在對Query進行rewrite的時候。
2. FST可以表達出Term倒排表所在的檔案偏移。
3. 倒排表使用SkipList結構。從上面的討論可知,求倒排表的交集、並集、差集需要各種SeekTo(docId),SkipList能對Seek進行加速。
skiplist備忘
如今大部分工具使用的倒排鏈已經不是簡單的連結串列了。一個常用,比如lucene中用的,叫skiplist,是一種高效的連結串列結構,在查詢、新增、刪除的時間複雜度上做到O(logN)。
查詢的過程很簡單,從頂層開始,往後查詢遇到節點的next()比待查的大或者到NIL了,節點不變下移一層繼續向後查詢,如此反覆,直到到了底層還沒查到。skiplist的資料也比較多,這裡就不贅述了。
連結串列集合操作
連結串列集合求交
lucene中用的是ConjunctionScorer ,大致過程是每條倒排鏈不斷的推進到小於等於當前最大節點的位置。當然實現細節還是很豐富的,作者很細心的把過程都列出來了,建議順著讀一邊。這裡摘抄部分:
首先把倒排鏈按第一個next排序:
檢視0~7的倒排鏈的第一個和最後一個是否相同,不同就開始找;取最後一個倒排的第一個元素8作為終點, 第一個連結串列開始找8
第0個連結串列 跳過1到了10,那麼8也不用找了都去找10就行了
第1根連結串列找到了11,那麼10也不用找了,找11,之後都這麼做
......
之後遇到11,本次交集操作找到一個11,
後續的計算也是同理,當然整個程式碼實現會比較複雜和討巧。基本思路就是每條倒排鏈能根據當前文件迅速跳過不符合的docid,由於倒排鏈可以用skiplist查詢,因此即使很長的倒排鏈,如果交集的數量很少,整個求解過程可以很快跳過不需要比較的節點。