劉靜
摘 要:索引是搜索引擎的核心概念,優(yōu)化索引提高使用效率是當前主要研究內容。文中研究了Lucene索引文件的內部結構,包括Lucene索引文件格式、文件組成、索引創(chuàng)建過程,并重點研究了段Segment文件的存儲結構。經研究表明,創(chuàng)建單一且重用的文檔實例以及提高使用的內存大小可有效提高索引使用效率。
關鍵詞:索引;Lucene;搜索引擎
中圖分類號:TP393 文獻標識碼:A
1 引言(Introduction)
在Lucence中包括了幾個基礎的概念,分別是索引、段、文檔、域和項。其中索引由段構成,段由文檔構成,因此索引可以理解為包含了多個文檔的序列。文檔由域構成,域由項構成,項是索引中最小構成單位,其本質是一個字符串。段是索引數(shù)據存儲的基本單元,多個段之間彼此獨立,當添加新的文檔時將生成新的段,且段可以合并。
充分理解Lucence索引的內部結構,對于在當前互聯(lián)網大數(shù)據、云存儲應用環(huán)境下較好使用Lucence進行具有重要意義。
2 索引文件結構(Index file structure)
2.1 倒排索引
對文本信息進行檢查的系統(tǒng)索引可以分為包括正排索引和倒排索引[1]。在實際使用中根據屬性值查找記錄的過程稱為倒排索引。倒排表中存儲了文檔中包含的單詞,文檔編號差值、單詞出現(xiàn)次數(shù)等,這些信息即組成了倒排索引項term。
倒排索引入口為索引項term,通過倒排索引可以找到包含每個term的文檔集合稱為記錄表,記錄表中包含文檔號及term在該文檔中的出現(xiàn)頻率。
Lucene為了使得基于term的檢索效率更高,索引存儲terms的統(tǒng)計數(shù)據。Lucene的索引采用了倒排索引。它可以列舉,包含一個term的所有文檔。這與自然關聯(lián)規(guī)則相反,即由documents列舉它所包含的terms。
2.2 域Fields
Lucene在存儲域數(shù)據時,域中文本被逐字的以非倒轉方式進行轉換,這些被倒排存儲的域數(shù)據可以被索引[2]。每個域的文本被拆分為多個索引項以便被高效索引,另一種方式為域中文本作為一個索引項進行索引。
2.3 片斷
Lucene索引可以由多個復合的子索引或片段構成。每個段是一個完全獨立的索引,它可以分離提取進行檢索。檢索過程如下:(1)當添加新的文檔時創(chuàng)建新的段;(2)對現(xiàn)有段進行合并。在索引檢索時,會涉及多個索引或段,因此每一個索引都隱含包括了一組段。段及文檔關系如圖1所示。
圖1 Lucene索引片段
Fig.1 The Lucene index fragments
2.4 文檔編號
在Lucene的內部對于每個文檔使用一個整數(shù)編號進行標識。初始情況下,第一個被加進來的文檔其文檔編號為0,之后加進來的文檔其編號自動遞增,采用自動遞增方式對文檔進行編號,編號不會出現(xiàn)重復。但需注意的是,文檔編號可以被手動更改。因此在維護時若出現(xiàn)更改情況,需特別考慮此編號是否在更大的范圍內被使用。通常的做法是為每個段空間設置文檔編號的范圍,以保證段之間的文檔編號不重復。
綜上所述,文檔編號若發(fā)生修改可能導致錯誤,因此文檔編號應先進行設計,在應用時不輕易、不頻繁修改文檔編號,只有當出現(xiàn)文檔在某段空間是統(tǒng)一的,且需要在整個系統(tǒng)中使用時必須修改情況下才進行修改。
3 索引文件(Index file)
3.1 索引文件
Lucene索引文件包含多種,其使用不同的文件擴展名來進行標識。同時文件名稱可以標識不同的版本。常見的文件擴展名有:fnm文件存儲域名和域屬性、fdt文件存儲域數(shù)據、fdx文件存儲在fdt文件中的偏移位置、frq存儲文件中項的位置數(shù)據等。對于段文件命名通常為segments_x,其中x即為最新修改版本,文件segments.gen存儲當前版本值。以下文件存在于每個索引index中,并且只有一份。
(1)Segments文件
索引中活動的Segments被存儲在segment info文件中,segments_N,在索引中可能會包含一個或多個segments_N文件。然而,最大一代的那個文件是活動的片斷文件(這時更舊的segments_N文件依然存在是因為它們暫時還不能被刪除,或者,一個writer正在處理提交請求,或者一個用戶定義的IndexDeletionPolicy正被使用。這個文件按照名稱列舉每一個片斷,詳細描述分離的標準和要刪除的文件,并且還包含了每一個片斷的大小。
(2)Lock文件
寫鎖文件名為“write.lock”,存儲在默認的索引目錄中。如果鎖目錄和索引目錄不一致的,寫鎖將被命名為“XXXX-write.lock”,其中“XXXX”是一個特殊唯一的前綴,來源于索引目錄的路徑。
(3)Deletable文件
Lucene的刪除機制類似于操作系統(tǒng)回收站,在執(zhí)行刪除操作時,相當于對索引進行了“刪除標記”并未真實刪除,當索引下次優(yōu)化或合并時再從索引中真正刪除。
(4)Compound文件
Compound文件格式成一個簡單的容器,其用來服務所有Segment包含的文件(除了.del文件)。
3.2 Segment
每個段中的文件是由后綴名來區(qū)分的。
(1)域集合信息
域的信息以集合形式存儲,域集合文件后綴為.fnm。在當前的情況下,fieldbits僅用于低位,索引的域值是1,未索引的域值為0,文件中各域根據次序進行編號,即認為值0是第一個域文件,值1是下一個域文件等。Fields將使用它們在這個文件中的順序來編號。需要注意的是,就像文檔編號一樣,field編號與片斷是相關的。
(2)域索引和域值
域值存儲表使用兩種文件存儲,分別為:域索引表(.fdx文件)文件,這個文件包含指向域值的指針FieldvaluesPosition,類型為UInt64類型,此指針指向了某域值在域文件中的位置。因為域值文件包括定長的數(shù)據信息,較易隨機訪問;域值(.fdt文件)文件,每個文檔的域值信息包括了字段FieldData、DocFieldData、FieldCount、FieldNum、Bits和value。
(3)項字典
項Term字典使用如下兩種文件存儲,第一種是存儲term信息(TermInfoFile)的文件,即.tis文件,另一種是存儲term信息索引的文件,即.tii文件。TermInfoFile文件按照Term來排序,排序方法首先按照Term的field名稱(按照UTF-16字符編碼)排序,然后按照Term的Text字符串(UTF-16編碼)排序。項的命名上前綴通常上是相同的,然后以字的后綴組成。
(4)項頻率數(shù)據
Term頻率數(shù)據文件(.frq文件)存儲容納了每一個term的文檔列表,以及該term出現(xiàn)在該文檔中的頻率(出現(xiàn)次數(shù)frequency,如果omitTf設置為fals時才存儲)。
關于skip levels,每一個term可以有多個skip levels。一個term的skip levels的數(shù)目等于NumSkipLevels=Min(MaxSkipLevels,floor(log(DocFreq/log(SkipInterval))))。對一個skip level來說SkipData記錄的數(shù)目等于DocFreq/(SkipInterval^(Level+1))。然而最低的skip level等于Level=0。例如假設SkipInterval=4, MaxSkipLevels=2,DocFreq=35,則skip level 0有8個SkipData記錄,在TermFreqs序列中包含第3、7、11、15、19、23、27和31個文檔的編號。Skip level 1則有兩個SkipData記錄,在TermFreqs中包含了第15和第31個文檔的編號。在所有l(wèi)evel>0之上的SkipData記錄中包含一個SkipChildLevelPointer,指向(referencing)level-1中相應)的SkipData記錄。在這個例子中,level 1中的記錄15有一個指針指向level 0中的記錄15,level 1中的記錄31有一個指針指向level 0中的記錄31。
(5)項位置
Positions位置信息數(shù)據文件(.prx文件)容納了每一個term出現(xiàn)在所有文檔中的位置的列表,可以利用這些信息來參與對索引結果的排序。如果在fields中的omitTf設置為true時將不會在此文件中存儲任何信息,并且如果索引中所有fields中的omitTf都設置為true,此.prx文件將不會存在。
(6)標準化因子文件
在Lucene 2.1版本之前,每一個索引都有一個norm文件給每一個文檔都保存了一個字節(jié)。對每一個文檔來說,那些.f[0-9]包含了一個字節(jié)容納一個被編碼的分數(shù),值為對hits結果集來說在那個field中被相乘得出的分數(shù)。每一個分離的norm文件在適當?shù)臅r候為復合的和非復合的segment片斷創(chuàng)建。在Lucene 2.1及以上版本,只有一個norm文件容納了所有norms數(shù)據:一個分離的norm文件在一個存在的segment的norm數(shù)據被更改的時候被創(chuàng)建,當field N被修改時,一個分離的norm文件.sN被創(chuàng)建,用來維護該field的norm數(shù)據。
(7)項向量文件
Term向量的支持是field基本組成中對一個field來說的可選項,它包含如下三種文件:a.文檔索引或.tvx文件:對每個文檔來說,它把偏移存儲進文檔數(shù)據(.tvd)文件和域field數(shù)據(.tvf)文件。b.文檔或.tvd文件:對每個文檔來說,它包含fields的數(shù)目,有term向量的fields的列表,還有指向term向量域文件(.tvf)中的域信息的指針列表。該文件用于映射出那些存儲了term向量的fields,以及這些field信息在.tvf文件中的位置。c.域field或.tvf文件:對每個存儲了term向量的field來說,該文件包含了一個term的列表,及它們的頻率,還有可選的位置和偏移信息。
(8)刪除的文檔
刪除的文檔(.del)文件是可選的,而且僅當一個segment存在有被刪除的文檔時才存在。即使對每一單個segment,它也是維護復合segment的外部數(shù)據。
4 索引創(chuàng)建過程(The index creation process)
為了使用Lucene的索引數(shù)據,必須先將其轉換為文本標記的數(shù)據流,并用它來創(chuàng)建一個文檔對象,其中包含的域成員來容納這些文本數(shù)據[3,4]。一旦你準備的文檔對象,可以調用IndexWriter類的adddocument方法傳遞對象到Lucene寫索引。當這樣做時Lucene進行分析數(shù)據,以便更適合索引。
文檔的索引過程是通過DocumentsWriter的內部數(shù)據處理鏈完成的,DocumentsWriter可以實現(xiàn)同時添加多個文檔并將它們寫入一個臨時的segment中,完成后再由IndexWriter和SegmentMerger合并到統(tǒng)一的segment中去。DocumentsWriter支持多線程處理,即多個線程同時添加文檔,它會為每個請求分配一個DocumentsWriterThreadState對象來監(jiān)控此處理過程。處理時通過DocumentsWriter初始化時建立的DocFieldProcessor管理的索引處理鏈來完成的,依次處理為DocFieldConsumers、DocInverter、TermsHash、FreqProxTermsWriter、TermVectorsTermsWriter、NormsWriter以及StoredFieldsWriter等。
DocFieldProcessorPerThread.processDocument()方法是處理一個文檔的調度函數(shù),負責整理文檔的各個fields數(shù)據,并創(chuàng)建相應的DocFieldProcessorPerField對象來依次處理每一個field。該方法首先調用索引鏈表的startDocument()來初始化各項數(shù)據,然后依次遍歷每一個fields,將它們建立一個以field名字計算的hash值為key的hash表,值為DocFieldProcessorPerField類型。如果hash表中已存在該field,則更新該FieldInfo(調用FieldInfo.update()方法),如果不存在則創(chuàng)建一個新的DocFieldProcessorPerField來加入hash表中。該hash表會存儲包括當前添加文檔的所有文檔的fields信息,并根據FieldInfo.update()來合并相同field名字的域設置信息。
建立hash表的同時,生成針對該文檔的fields[]數(shù)組(只包含該文檔的fields,但會共用相同的fields數(shù)組,通過lastGen來控制當前文檔),如果field名字相同,則將Field添加到DocFieldProcessorPerField中的fields數(shù)組中。建立完fields后再將此fields數(shù)組按field名字排序,使得寫入的vectors等數(shù)據也按此順序排序。之后開始正式的文檔處理,通過遍歷fields數(shù)組依次調用DocFieldProcessorPerField的processFields()方法進行,完成后調用finishDocument()完成后序工作,如寫入FieldInfos等。
5 結論(Conclusion)
Lucene自發(fā)布至今已有近15年時間,近幾年互聯(lián)網的快速發(fā)展更使得產生的數(shù)據呈指數(shù)級增長,Lucene面對海量數(shù)據進行處理,因此在檢索時針對索引的優(yōu)化至關重要。牢固掌握Lucene索引原理對于解決當前大數(shù)據環(huán)境下數(shù)據檢索以及提高檢索效率打下良好基礎。
參考文獻(References)
[1] 王冬.一種增量倒排索引結構的設計與實現(xiàn)[J].吉林大學學 報,2007,45(06):953-958.
[2] 黃軼文.搜索引擎原理與快速開發(fā)應用[J].科技信息,2010, (36):570-571.
[3] 何偉,等.基于Lucene的全文搜索引擎的設計與實現(xiàn)[J].2006, 25(9):88-90.
[4] 李曉麗,杜振龍.基于Lucence的個性化搜索引擎研究[J].計 算機工程,2010,36(19):258-260.
作者簡介:
劉 靜(1982-),女,碩士,講師.研究領域:計算機應用 教學.