文章目錄
一、索引構建影響因素
索引構建是指一篇文檔轉換成倒排索引的整個過程;
(1)需要考慮的因素有記憶體大小、CPU時鐘頻率等;比如如果記憶體特別大,則能夠把全部的文檔都放入記憶體,並很快就能構建成倒排索引;
(2)我們需要把儘可能多的內容放在記憶體;
(3)需要考慮尋道時間,因此必須要把連續讀取的資料放在連續的塊中;
將文檔集變成term-->docID後,詞項-文檔ID對的數目是token的數目;
二、BSBI
我們這裡考慮的是大文檔集(不能把全部的文檔都放入記憶體)。
顧名思義,BSBI(Block Sorted-Based Indexing)是基於塊排序的;操作流程如下:
(1)把整個文檔集分成大小相同的部分(每個部分正好是一個塊大小)並放入記憶體;
(2)把每個部分解析成詞項ID->文檔ID對;(我們為了能夠使得索引構建的效率更高,我們用詞項ID代替詞項本身,當然同時需要維護一個詞項->詞項ID的映射表,並把他放入記憶體);
(3)把這個塊的詞項ID->文檔ID對按照詞項排序,並對相同詞項ID對應的文檔ID構建臨時posting;
(4)將此結果寫回磁碟,並進行下一個block的解析;
(5)當全部的文檔集都解析完畢後,對每個block的倒排索引進行合并,並最後成為一個完整的倒排索引;
而BSBI的核心演算法是(2),(3),因此其核心演算法的複雜度為O(TlogT),在這個複雜度中並沒有考慮(5)步的外部歸併排序;因此只針對解析文檔+產生臨時posting;
三、SPIMI
BSBI缺點:需要維護詞項->詞項ID的映射表,如果文檔集很大,則這個映射表也會很大;
SPIMI(Simple Pass in memory indexing),操作流程如下:
(1)把整個文檔集都分割成詞項->文檔ID對;
(2)把這個一系列的詞項->文檔ID對作為一個流,如果還有記憶體,則逐個進入記憶體;
(3)記憶體中預先已經構建了一個dictionary(hash實現),因此只需要利用詞項尋找到文檔ID應該放入的位置,並放入文檔ID即可;
(4)當記憶體滿時,將dictionary按照詞項進行排序,並將排序後的dictionary和posting寫回磁碟;
(5)將全部的文檔集解析完後在磁碟中應該有多個已排序的dictionary-posting;將這些合并即可;
SPIMI的核心演算法為(2)(3),因此演算法複雜度為O(T);
四、Map-reduce
上面所講的都只是針對一般大的文檔集,但是如果是對于海量的文檔集,則在一台機器處理明顯是不行的;因此我們想到了分而治之的思想;
主要思想:將文檔集分布在電腦叢集上進行處理,採用Master-Slave模式,Master電腦控制處理過程,比如一台電腦在處理文檔集時突然壞了,則Master會將此電腦處理的文檔集任務交給另一台機器處理;
Map階段:將文檔集劃分成n個資料片,並通過分析器進行處理,變成排好序的詞項->文檔ID對,這就是一般的BSBI或SPIMI演算法;
Reduce階段:比如將每台機器的dictionary劃分成a-i和j-z兩個部分,然後將a-j部分統一交給一個倒排器完成,因此這裡只需要兩個倒排器即可;
注意:
(1)分析器和倒排器是一台電腦,並且一台機器既可以作為倒排器也可以作為分析器;
Map階段細化:
(1)文檔集存在一台獨立的機器中,將文檔集分成資料片,並分別傳送到作為分析器的機器中(這裡需要考慮IO時間);
(2)進行BSBI或者SPIMI分成詞項ID-->文檔ID(涉及比較次數消耗時間);
Reduce階段細化:
(1)將分區檔案通過IO傳送到倒排器中(這裡需要考慮IO時間);
(2)將每個倒排器中的詞項ID-->文檔ID排序 O(nlogn) n為詞條數目;
(3)將倒排記錄表寫到獨立的機器中; (注意:這裡需要考慮dictionary的大小和posting的大小,dictionary的大小是詞項大小,posting大小是詞條大小,並且注意IO時間);
五、動態索引構建
在以上討論中,都是以文檔不變化為前提,但實際上文檔會更新、插入、刪除等;因此我們需要引入動態索引;
主要思想:主索引繼續維護,構造一個輔助索引(表示添加的文檔),維護一個無效位向量(表示刪除的文檔),當輔助索引足夠大時,就和主索引合并;
在檢索時,我們必須要將主索引和輔助索引的檢索結果合并,並在無效位向量中進行過濾即可;
改進方法:
引入log(T/n)個索引I0,I1,....Ii......;每個索引大小分別為(2^i)*n;
這些索引構建過程:
在記憶體中始終維護一個輔助索引;
(1)一開始當輔助索引滿時,就構建I0並將I0存入磁碟,清空輔助索引;
(2)輔助索引第二次滿時,和I0合并,並成為I1(I0被去除);
(3)輔助索引第三次滿時,構建I0;
(4)輔助索引第四次滿時,將I0、I1和輔助索引合并,成為I2(I0和I1被清除);
以此類推,可以看到有一個規律:構建索引的過程是以位元增加的方式構建的;即:
I3 I2 I1 I0
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
在檢索時,我們要合并從I0到In索引的結果,並過濾無效位向量,因此比較麻煩;
六、訪問授權
一般倒排索引的posting都是按照文檔ID進行排序,這樣有助於壓縮,而且插入資料時只需要在最後;但是對於ranked retrieval來說,需要按照權重進行排序,但是如果要添加資料,則需要掃描一遍確定插入位置;
一般地,訪問授權是指一個使用者對於文檔是否有權訪問,通過ACL(Access Control List)進行處理,而存取控制表也可以用一個倒排索引結構進行組建;
dictionary表示每個使用者,而posting表示使用者所能訪問的文檔ID;簡單的來說就是一個使用者-文檔ID矩陣;