1. 程式人生 > >正排索引(forward index)與倒排索引(inverted index)

正排索引(forward index)與倒排索引(inverted index)

一、正排索引(前向索引)

正排索引也稱為"前向索引"。它是建立倒排索引的基礎,具有以下欄位。

(1)LocalId欄位(表中簡稱"Lid"):表示一個文件的區域性編號。

(2)WordId欄位:表示文件分詞後的編號,也可稱為"索引詞編號"。

(3)NHits欄位:表示某個索引詞在文件中出現的次數。

(4)HitList變長欄位:表示某個索引詞在文件中出現的位置,即相對於正文的偏移量。

由於一篇文章中的某些詞可能出現多次,而且位置不同,而全文檢索的本質要求是把這些位置標識出來,因此HitList中的每個命中都表示索引詞在文件的某個位置中出現了一次,這個序列為單調遞增序列。基於遊程編碼的方法,變升序序列為差分序列,採用前文提到的Variable Byte Coding方法編碼可以大大壓縮正排索引的HitList欄位。

在正排索引中LocalId採用升序序列編號(假定編號採用自增1的方式遞增),這為下面的計算創造條件。進行倒排索引的轉化時,由於正排索引中Lid天然的有序性,因此在正排索引轉化為倒排索引的建立過程中,自然可以保證倒排索引中每個詞彙對應的文件編號也是有序的,倒排索引將在下一節中介紹。

這樣,正排索引如圖4-3所示。

 
圖4-3  正排索引
通過一個例子來了解正排索引的建立過程。假定存在這樣一個編號為1的文件,其全文為"走進搜尋引擎,學習搜尋引擎",分詞的結果為"走進/搜尋引擎/學習/搜尋引擎"。不妨為"走進"編號為"T1","搜尋引擎"編號為"T2","學習"編號為"T3"。通過計算得到"走進"出現1次,出現位置為1;"搜尋引擎"出現兩次,出現位置為3和9(圖中存放的為未壓縮的差分序列3和6);"學習"出現1次,出現位置為7。建立的正排索引如圖4-4所示。

 
圖4-4  正排索引示例

HitList是變長的,因此需要NHits這個欄位標記其長度,這樣才能讀出全部的正排索引資料。假定每個域都是一個位元組大小,而HitList變長。在上面這個例子中,假定這個正排索引依次存放在一個數組Array中,則當讀取到Array[2]時,讀取的內容為T1的NHits,讀出的結果為1。由於T1出現了1次,因此在T1的HitList中僅存放了一個位置資訊。這樣在讀取Array[3]後,接下來讀取Array[4]則能夠判斷為下一個索引詞T2。正是由於NHits的這種表示長度的作用,全部的資料才能被有效地讀取。

最後用NULL表示為一個結束符的這種設計是很巧妙的;否則,正排索引可能是這樣,如圖4-5所示。

 
圖4-5  冗餘存放DocId的正排索引

在圖4-5中,為了結構化資料的需要,在去掉表示結束符的NULL後,正排索引必須冗餘地存放DocId,因此一個標記結束符的欄位有效地壓縮了正排索引的大小。

本質上說,正排索引以文件編號為視角看待索引詞,也就是通過文件編號去找索引詞。任給一個文件編號,能夠知道它包含了哪些索引詞、這些索引詞分別出現的次數,以及索引詞出現的位置。然而全文索引是通過關鍵詞來檢索,而不是通過文件編號來檢索,因此正排索引不能滿足全文檢索的要求。

雖然正排索引不能滿足全文檢索的需要,但是正排索引為建立倒排索引創造了有利條件,是計算倒排索引的不可缺少的一環。

二、倒排索引

倒排索引是一種以關鍵字和文件編號結合,並以關鍵字作為主鍵的索引結構。倒排索引分為兩個部分。

(1)第1個部分:由不同索引詞(index term)組成的索引表,稱為"詞典"(lexicon)。其中儲存了各種中文詞彙,以及這些詞彙的一些統計資訊(例如出現頻率nDocs),這些統計資訊用於各種排名演算法(Ranking Algorithm) [Salton 1989;Witten 1994]

(2)第2個部分:由每個索引詞出現過的文件集合,以及命中位置等資訊構成,也稱為"記錄表"(posting file)或"記錄列表"(posting list)。如圖4-6所示。

 
(點選檢視大圖)圖4-6  倒排索引

左邊的表結構(詞典)記錄索引詞Id號、匹配該索引詞的文件數量,並匹配文件在記錄檔案內的偏移量,通過這個偏移量就可以讀取記錄檔案對應區域的資訊。例如在圖4-6中,通過讀取T1的偏移量x,讀取在記錄檔案中T1命中的相關文件Doc1、Doc2和Doc3的相關資訊。

右邊的表結構(記錄表)記錄文件編號(DocId)、索引詞在該文件的命中個數(NHits),以及命中域的列表(HitList)。例如在圖4-6中,記錄檔案顯示了T2關鍵詞在Doc1中出現了3次。

圖4-6所示的倒排索引示例中,以索引詞T2為例,T2在兩個文件中出現。通過偏移量在記錄檔案中找到了存放與T2有關的資訊,即T2匹配的Doc1和Doc2兩個文件,並且在Doc1中出現了3次,位置分別為3、5和7(圖中3、2和2表示為差分序列後的實際值,即3、5-3和7-5)。

注意到這種按照索引片語織文件的方式,在索引詞WordId一邊,其Id號不會重複;而在DocId一邊,由於每個文件都可能包含多個索引詞,DocId的重複非常普遍,因此對DocId就需要進行大規模的壓縮。

壓縮編碼也採用Variable Byte Coding編碼方法進行壓縮,首先對DocId排序,接下來將DocId的遞增序列為差分序列,最後用Variable Byte Coding編碼方法進行壓縮編碼。例如這樣的DocId序列(22,5,9,1),通過排序得到(1,5,9,22),變差分序列得到(1,4,4,13),壓縮編碼後得到(2,8,8,26),對於小於128的數進行壓縮編碼,相當於乘2(詳細參見本章第三節中的相關內容)。

最後,在倒排索引中,按照何種順序存放DocId更加有利於檢索呢?在圖4-6中,T1這個詞有Doc1、Doc2、Doc3與之相匹配,也就是在這些文件中都出現了T1,那麼在倒排索引的記錄表中,哪個文件編號先存放,哪個文件編號後存放呢?這種存放順序的策略大致有如下3種。

(1)按照DocId升序存放。

(2)按照索引詞在文件中出現次數降序存放。

(3)記錄表分塊存放,塊內按DocId升序存放,塊間按PageRank值降序存放。

對於方案1來說,它有助於在多關鍵詞查詢中,得到相同的DocId(在第六章中介紹查詢系統時,會提到因為DocId有序而為查詢帶來的好處)。並且能夠對DocId進行壓縮編碼,同時降低磁碟I/O的開銷。

對於方案2來說,按照索引詞Id在文件中出現的次數降序排序,因為索引詞出現次數多的文件與查詢關鍵詞的相關性越好(這裡,索引詞和關鍵詞是同一個詞,在索引系統中稱為"索引詞",在查詢系統中稱為"關鍵詞"或"查詢詞"),這是很自然的,檢索就是檢索哪些與查詢詞相關性高的文件。文獻[S. Brin 1998]闡述了一種折中的設計方案,即不同的索引詞命中區分對待,對於索引詞在標題或者錨文字(Anchor)命中的文件,以及命中資訊存放在一個記錄表中,不妨稱為"表A",表內資料按DocId排序;命中其他位置的文件及其命中資訊存放在另一個記錄表中,稱為"表B",同樣表內資料也是按照DocId排序。這樣對於每個索引詞的查詢,優先在表A中查詢。只有當結果數不夠時,再到表B中查詢。這樣既照顧到了壓縮儲存的需要,也照顧到了相關性,通常標題中的詞大多在正文中會多次出現。當然這種折中的方法有時也不夠合理,它過分倚重於錨文字的關鍵詞,常常被針對這種演算法作弊的網頁設計者利用。

對於方案3來說,一方面照顧到了方案1的索引壓縮功能(文件按序儲存);另一方面照顧了重要的文件在檢索過程中優先被檢索的需要,而且防止了方案2中由網頁設計者作弊可能帶來的麻煩。有些網頁設計者在網頁中正文,錨文字中堆砌大量經常被查詢的重要關鍵詞,因此方案2在設計上不可避免的缺陷容易被利用。當然PageRank演算法也會被作弊者利用,然而PageRank的作弊較為困難,所以方案3是較為理想的解決方案。

最後,總結一下正排索引和倒排索引的關係。本質上說,存在這樣兩個空間,一個稱為"索引詞空間",一個稱為"文件空間"。正排索引可以理解成一個定義在文件空間到索引片語空間的一個對映,任意一個文件對應唯一的一組索引詞;而倒排索引可以理解成一個定義在索引詞空間到文件組空間的一個對映。任意一個索引詞對應唯一的一組該索引詞其命中的文件。因此從文件到正排索引,進而從正排索引到倒排索引就是理順這種關係的過程。使得給出一個索引詞,就能通過倒排索引能夠找到其命中的文件,以及位置資訊。


from: http://book.51cto.com/art/201105/262903.htm