1. 程式人生 > >lucene倒排索引--fst和SkipList的結合

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查詢,因此即使很長的倒排鏈,如果交集的數量很少,整個求解過程可以很快跳過不需要比較的節點。