1. 程式人生 > >談談lucene倒排索引的儲存方式(3-3)

談談lucene倒排索引的儲存方式(3-3)

            當輸入abe時由於abcd、abcde、abcdef、abcdf、abcdg以abcd為字首的個數為5個已經超過MIN_BLOCK_SIZE個數,因此達到寫成一個Block的條件,由於MAX_BLOCK_SIZE=4所以對這5個item需要進一步按照MIN_BLOCK_SIZE3個為一組進行拆分,即abcd、abcde、abcdef會寫到一個Block(該Block也是一個leafBlock,因為它的元素只有詞)中,除了字首abcd,其餘的字尾以及postings元資料(經過壓縮)會全部寫入到termsOut檔案流中,對於該Block有以下重要屬性prefix, startFP, hasTerms, isFloor, floorLeadLabel, subIndices,其中prefix表示公共字首即abcd,startFP表示termsOut檔案流指標(通過該指標可以從tim檔案中解析出該Block中每個詞的資訊),hasTerms表示該塊是否包含詞(很明顯該Block中全部都是詞),isFloor為True表示該塊由於超過MAX_BLOCK_SIZE個數進行了進一步分塊,floorLeadLabel該塊中第一個詞的第prefixLen個字元(該塊為-1),subIndices表示子塊的索引(該塊沒有子塊)。然後abcdf與abcdg會同樣寫入到一個新塊中,不過此時prefix記錄的是abcdf,floorLeadLabel記錄的是f。寫完這兩個塊就得想辦法如何能定位這兩個Block了:首先這兩個塊的Floor都為True,先寫入第一個塊的fp、hasTerm標記和isFloor,再寫入剩餘Block的個數對每個Block寫入floorLeadLabel(主要用於查詢某個詞時可以預判,如果不存在就無需載入該塊下所有的詞),這些資訊最終會轉換成位元組陣列並且和字首abcd一起寫入FST中,該FST是儲存在第一個Block中的

,最後將pending列表中的abcd、abcde、abcdef、abcdf、abcdg替換成該Block,於是pending列表中的元素為pendingTerm:abc、pendingBlock:abcd以及新增的pendingTerm:abe。

           繼續新增abf、abg、abh,此時pending列表中有6個entry,其中5個term,1個block。最後需將這6個entry按照MIN_BLOCK_SIZE和MAX_BLOCK_SIZE設定的閾值繼續分塊:首先term:abc、block:abcd、term:abe會組成一個新的Block,其中在寫入block:abcd時記錄的是block的檔案指標,

然後term:abf、abg、abh也會形成一個新的Block,最後這兩個新的Block會按照前面所述的方式一起寫入FST中並儲存在第一個Block中。至此倒排索引的儲存方式算是分析結束了,其實lucene的倒排索引的邏輯檢視還是樹狀的(最終會以FST的形式儲存索引資料由於FST可以共享字尾所以FST是個圖,但是它也可以認為是對樹的一種優化,我們可以認為FST是一種共享字尾的字首樹),早期實現的跳躍連結串列也是樹狀的,而關係庫中常用的B樹也是樹狀的,它們在查詢的效率以及讀寫的實時性上有一定的差異性,以後對這三種形式的樹進行仔細的分析。後面還是著重對lucene的索引合併、多執行緒寫入、實時性以及事務性方面進行分