如何構建倒排索引,我們將這個過程叫做“索引構建”。如果我們的文檔很多,這樣索引就一次性裝不下記憶體,該如何構建。
硬體的限制
我們知道ram讀寫是隨機的操作,只要輸入相應的地址單元就能瞬間將資料讀出來或者寫進去。但是磁碟不行,磁碟必須有一個尋道的過程,外加一個旋轉時間。那麼只有涉及到磁碟,我們就可以考慮怎麼節省I/O操作時間。
【注】作業系統往往以資料區塊為單位進行讀寫。因為讀一個位元組和讀一個資料庫所耗費的時間可能一樣多。
基於塊的排序索引方法(BSBI)
通常建立一個倒排索引:我們需要掃描一遍文檔得到所有詞項-文檔ID對;然後分別以詞項為主鍵、文檔ID為此次鍵進行排序;最後我們可能還要統計文檔頻率和詞項頻率。對於小文檔來說,這一過程在記憶體中完成是沒有問題的,但是對於文檔集合較大的,可能在記憶體中無法進行。
BSBI第一步,在搜集詞項的時候將其映射為ID(為什麼映射為ID,提高效率)。
BSBI第二步,將文檔分成多個大小相同的小檔案(block)。
BSBI第三步,將每個小檔案對詞項ID-文檔ID進行排序,並將中間產生的臨時排序檔案放在磁碟中。
BSBI第四步,將排序好的小檔案進行歸併排序得到最終的倒排索引。由於記憶體不足,我們必須使用基於磁碟的外部排序演算法(多路歸併排序,敗者樹http://blog.csdn.net/lsjseu/article/details/11708587)。
記憶體式單遍掃描索引構建(SPIMI)
BSBI構建方法具有很好的擴充性,但是需要一種映射為ID的資料結構,對於大規模文檔,該結構可能導致記憶體放不下。
SPIMI不是用ID儲存,而是直接採用詞項本身。
SPIMI第一步,CPU記憶體雖然小,但是還可以構建一些,所以SPIMI現在記憶體構建索引,直到記憶體滿了。這是,SPIMI將構造好的索引寫入磁碟檔案中存放。
SPIMI第二步,在第一步最後存放的時候,需要對詞典進行排序,意思就是排序後再存放到磁碟。
SPIMI第三步,將多個塊合并成最後的倒排索引。
【注】SPIMI與BSBI區別,BSBI是邊處理每個小檔案,邊就排好序。而SPIMI處理完了每個小檔案,然後對小檔案整體排序。
分布式構建方法
實際當中,檔案都非常大,一台機子可能處理不過來。這是可利用分布式系統來構建索引。這裡我們需要用到MapReduce構架。MapReduce將一個龐大的處理任務分成子任務,然後分發到各個計算節點進行計算,計算完成後歸併得到最後的結果。
各個子任務並不預先分配到某個節點,而是在運行過程中,由主控節點動態分配。這樣的話,算得快的節點,可以分配任務多一點(因為很快就計算完了嘛,可以重新分配心的任務了),慢點的節點可能相對較少一點。或者說如果某台機子如果算不動了,可以把它的任務挪到其他節點上去完成。
動態構建索引方法
上面的方法都是靜態構建索引,就是說我的文件不變,但是有可能存在這樣一種情況,我的文件在不斷變化。那麼,此時我們就需要動態構建索引。
此時,我們可以構建兩個索引,一個大的主索引,一個小的輔助索引存在記憶體中。檢索時,我們就可以同時遍曆這兩個索引,將兩個索引結果進行歸併操作。
同時,如果我們的輔助索引很大的時候,我們就它合并到主索引中去。
後記
其實,倒排表的也是很大的,那麼我們怎麼去壓縮它呢。請看下文:http://blog.csdn.net/lsjseu/article/details/12239967