通過Lucene索引檔案學習Lucene索引過程
阿新 • • 發佈:2019-02-08
#DocPosition 記錄文件在fdx的起始地址,這樣通過改地址能夠直接定位到文件
(4)fdx
#FORMAT 整型,4個位元組,3.6.2常量為3,對應00 00 00 03
#DocPosition 每個文件對應一個開始地址,一共有3個文件,每個開始地址佔用一個Long即8個位元組
(5)fdt,fdx建立資料物件呼叫關係
這個過程只是組裝正向資訊的過程,此時,還有沒重新整理到磁碟上
(6)fdt,fdx重新整理磁碟物件呼叫關係
2.tis,tii
tis,tii儲存(詞Term)反向索引資訊,tis儲存詞的資料資訊,tii儲存詞的索引(位置)資訊
tis資料資訊在addDocument已經完成最重要的方向索引結構,在往檔案上刷的時候只是重新排序和合並不同域資訊等處理。 IndexWriter.addDocument | ---DocumentsWriter.updateDocument | ----DocumentsWriterThreadState | ------DocFieldProcessorPerThread.processDocument | ------DocFieldProcessorPerField.processFields 這個方法用於組裝最重要的方向索引結構,這裡有幾點需要了解的地方 #Lucene的反向索引並不傳說中的連結串列的方式儲存的,而是用幾個陣列及輔助資訊儲存的。 #該方法是以域為單位分詞的,也就是說相同的詞在不同的域是分別儲存的,在flush的時候才做合併處理。 反向資訊儲存資料結構是有主儲存結構和輔助結構共同完成的 #主儲存結構有三個陣列,分別是bytePool,charPool,intPool charPool 儲存分詞後的Term資料資訊 bytePool 儲存Term的詞頻及位置資訊,初始化每個詞有10個位元組空間,前5個位元組儲存詞頻資訊,後5個位元組儲存詞位置資訊 intPool和bytePool是配合使用的,每個詞在intPool分配兩個位元組,用於指向bytePool的儲存詞頻和位置資訊的地址, #輔助結構有postingsHash,postingsArray,fieldState等構成. postingsHash 記錄詞的是否出現過, postingsArray 記錄當前此在charPool,bytePool,intPool的位置等資訊 fieldState 記錄當前域的最大詞頻、當前詞頻,該詞在域的postion和offset資訊 通過上面一系列物件的組合就得到了反向索引的初步結構. 通過一個例項展示lucene反向索引是如何儲存的,例如對下面兩條記錄進行索引 id name syno 5159 依雲50ml evian依雲,evian 5160 依雲150ml evian依雲,evian 讀入5159,個物件變化如下: 首先用postionsHash判斷該詞在該域上是否儲存過,5159沒有儲存過 charPool 5,1,5,9, , ?? 5169後面跟一個佔位符,用於詞的分隔 bytePool 0,0,0,0,16,0,0,0,0,16 ?? 前五個位元組儲存該詞的詞頻,第一個位元組儲存這個詞第一次出現的詞頻, 因為只有下一個域也hash到這個詞,才能+1,目前是0,第二組5個位元組用於儲存詞在該域的位置。 intPool 0,6 ?? 0指向該詞在byte寫入的位置,因為5159詞頻沒有發生變化,所以第一個位元組為0, 5159這個詞已經儲存在bytePool[5]的位置上,所以下一個寫入的位置+1變成6 位置儲存的計算是位運算,例如第一個位置0<<1等於0,第二個位置1<<1等於2,以此類推。 通過StandardAnalyzer分析name域 讀取"依" charPool 5,1,5,9, ,依, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,2,0,0,0,16 intPool 0,6,10,16 讀取"雲" charPool 5,1,5,9, ,依, ,雲, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,4,0,0,0,16 intPool 0,6,10,16,20,26 讀取"50ml" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16 intPool 0,6,10,16,20,26,30,36 通過StandardAnalyzer分析syno域 讀取"evian" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,46 讀取"依" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, , ??注意,目前相同詞在不同域是獨立儲存的 bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,2,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,46,50,56 讀取"雲" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,46,50,56,60,66 讀取"evian",這裡變化很關鍵 通過postionsHash發現該域evian儲存過,獲得postingsArray定位到intPool位置,不在寫入evian,intPool[9]++變成了47 charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,2,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,47,50,56,60,66 讀取"5160" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, ,5,1,6,0 bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,2,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16,0,0,0,0,16,0,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,47,50,56,60,66,70,76 讀取"依" 通過postingsHash得知該詞在該域儲存過,charPool不需要新增新詞,通過postingsArray定位到intPool位置,將詞頻加1,將postion+=1 charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, ,5,1,6,0 bytePool 0,0,0,0,16,0,0,0,0,16,1,0,0,0,16,0,2,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,2,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16,0,0,0,0,16,0,0,0,0,16 intPool 0,6,11,17,20,26,30,36,40,47,50,56,60,66,70,76 下面依次類推 有一種情況,就是如果一個詞在域出現的次數大於4次,儲存空間就不夠了,這有一個跳躍表的概念。 &&&至此,反向索引資訊已經初步完成構建。 在寫入tis和tii資訊之前,會先把詞頻(frq)和詞位置(prx)寫入到檔案中 (1)frq儲存term的文件id及詞頻資訊,這裡有兩點需要注意 #frq是以域順序儲存的,例如會先儲存id域所有詞的詞頻,才會儲存name域的詞頻 #文件每個域id是以差值規則儲存的,例如name域有一個term,分別在文件0,1,2出現過1次,Lucene儲存文件id的值分別是0<<1|1 ,1<<1|1 2<<1|1,分別儲存的是1,3,5 如果詞頻大於1,那麼文件id儲存規則為id<<1,並且還有一個位元組儲存頻率 id syno 5159 evian依雲,evian 5160 evian依雲,evian 例如上面的資訊,frq儲存過程如下: #讀入5159, 文件id=0, 0<<1|1 = 1, frq檔案儲存01 #讀取5160, 文件id=1, (1-0)<<1|1 = 3 儲存03 #讀取evian 此時"evian"在文件id=0出現2次,文件id=1出現2次,儲存00 02 01 02 #讀取"依" 此時"依"在文件id=0出現1次,文件id=1出現1次, 儲存01 03 #讀取"雲" 此時"依"在文件id=0出現1次,文件id=1出現1次, 儲存01 03 在lucene儲存詞的順序的時候會通過hash的方式儲存到陣列的位置,上面的儲存方法是正確的,詞的順序會有所不同 (2)prx儲存詞的位置資訊 通frq一樣,prx是以域順序儲存的,例如會先儲存id域所有詞的詞頻,才會儲存name域的詞頻 id syno 5159 evian依雲,evian 5160 evian依雲,evian 例如上面的資訊,prx儲存過程如下: 讀取5159 在文件id=0在第0個位置,prx檔案儲存00 讀取5160 在文件id=1在第0個位置,prx檔案儲存00 讀取evail 在文件id=0,的第一個位置和第三個位置 在id=1第一個位置和第三個位置,所以儲存00 03 00 03 讀取"依" 在文件id=0的第一個位置和id=1的第一個位置,所以儲存01 01 讀取"雲" 在文件id=0的第二個位置和id=1的第二個位置,所以儲存02 02 在IndexWriter.flush方法分別依次往磁碟刷入frq,prx,tis,tii資訊 tis格式如下: FORMAT --- TermCount --- indexInterval --- skipInterval --- maxSkipLevels --- TermInfo ... (Int) (Long) (Int) (Int) (Int) -------- | StartLength --- Length --- DataBytes --- fieldNumber --- docFreq --- freqPointer --- proxPointer (VInt) (VInt) (bytes) (VInt) (VInt) (VLong) (VLong) @FORMAT 當前.tis檔案版本號 3.6.2(-4) @TermCount 詞個數,初次寫入0佔位,在關閉檔案的時候,才寫入真實的個數 @indexInterval 索引間隔(128) @skipInterval 跳過間隔(16) @maxSkipLevels 最大跳躍層數(10) @TermInfo 詞資訊 @#StartLength 開始長度 @#Length 詞所佔的位元組數 @#DataBytes 詞資料資訊 @#fieldNumber 域序號 @#docFreq 該詞在文件出現的頻率 @#freqPointer 詞頻指標,儲存該詞頻指標和最後一個詞頻指標之差 @#proxPointer 位置指標,儲存該詞位置指標和最後一個詞位置指標之差 @#skipOffset 可選項,如果詞頻大於skipInterval,則該位記錄位置偏移 tii格式如下 FORMAT --- TermIndexCount --- indexInterval --- skipInterval --- maxSkipLevels --- TermIndexInfo ... (Int) (Long) (Int) (Int) (Int) -------- | StartLength --- Length --- DataBytes --- fieldNumber --- docFreq --- freqPointer --- proxPointer --- filePointer (VInt) (VInt) (bytes) (VInt) (VInt) (VLong) (VLong) (VLong) @FORMAT 當前.tis檔案版本號 3.6.2(-4) @TermIndexCount 詞索引個數,初次寫入0佔位,在關閉檔案的時候,才寫入真實的個數 @indexInterval 索引間隔 預設(128) @skipInterval 跳過間隔 預設(16) @maxSkipLevels 最大跳躍層數 預設(10) @TermInfo 詞資訊 @#StartLength 開始長度 @#Length 詞所佔的位元組數 @#DataBytes 詞資料資訊 @#fieldNumber 域序號 @#docFreq 該詞在文件出現的頻率 @#freqPointer 詞頻指標,儲存該詞頻指標和最後一個詞頻指標之差 @#proxPointer 位置指標,儲存該詞位置指標和最後一個詞位置指標之差 @#filePointer 域索引檔案指標 frq,prx,tis,tii儲存流程 IndexWriter.doflush | -----DocumentWriter.doFlush | ----DocFieldProcessor.flush | -----DocInverter.flush | -----TermHash.flush | ----- FreqProxTermsWriter.appendPostings 在這個方法依次完成frq,prx,tii,tis寫入。
3.nrm
nrm檔案儲存著所有文件每個域的評分因子,這個因子的演算法需要一些預知識,這裡面評分因子的演算法在評分那篇日誌會細說
.nrm檔案儲存結構: FORMAT ----- perFieldNorm (Int) (byte) @FORMAT nrm版本號,預設{'N','R','M',-1} @perFieldNorm 文件域標準化因子的值 .nrm儲存流程 IndexWriter.doflush | -----DocumentWriter.doFlush | ----DocFieldProcessor.flush | -----DocInverter.flush | ----InvertedDocEndConsumer.flush
4.fnm
儲存了段的一些資料資訊,例如一個段(segement)包含多個域(field),每個域都包含著一些元資料資訊,儲存在.fnm檔案中,.fnm檔案格式如下: FORMAT --- FIELDSIZE ---- fieldInfo .. (VInt) (VInt) ----- | fileldName ---- fieldAttribute (String) (byte) ------ | -- -- -- -- -- -- -- -- (如果索引文件及詞頻) (如果索引文件) (儲存有效負載Payloads) (omitNorms標準化因子) (是否儲存詞向量) (是否被索引)
@FORMAT FNM版本號 -3(3.6.2) @FIELDSIZE 域數量 @fieldInfo 域欄位資訊 @#fieldName 域名稱 @#fieldAttribute 域屬性欄位,一個位元組,8位,每位代表不同的屬性含義,注意:只用了6位
5.segments_n
segments_n儲存段的元資料資訊
FORMAT -- VERSION -- counter --segSize --- SegmentInfo .. --- userData --- digest
(int) (long) (int) (int) ---- (stirngstringMap) (Long)
| version --- name ---- docCount ---- delGen ---- docStoreOffset ----hasSingleNormFile -- normGen
---- isCompoundFile --- delCount --- hasProx --- diagnostics --- hasVectors
(String) (String) (Int) (Long) (Int) (byte) (Int)|變長
(byte) (int) (byte) (stirngstringmap) (byte)
@FORMAT 索引格式版本號 -11(3.6.2)
@VERSION 索引版本(取當前時間)
@counter 下一個新段的名稱,例如.fdt,.fdx..
@segSize 段大小,例如0.fnm,1.fnm,段大小為2
@SegmentInfo 段資訊,如果有多個段,則有多個段資訊
#@version lucene版本號"3.6.2"
#@name 段名稱,例如第一個段"_0"
#@docCount 該段包含的文件數
#@delGen
#@docStoreOffset 如果為-1,則此段獨立儲存域資訊和詞向量,檔案為0.fdt,0.fdx,如果不為-1,則域資訊和詞向量則記錄的偏移量
#@hasSingleNormFile 如果為1,則搜尋評分因子則存在.nrm檔案中,否則每個域則單獨儲存在.fN檔案中
#@normGen
#@isCompoundFile 是否為複合檔案
#@delCount 刪除文件數量
#@hasProx 是否儲存詞頻和位置資訊
#@diagnostics 作業系統資訊&jvm版本等資訊
#@hasVectors
@userData 使用者設定資訊
@digest 摘要
6.segments.gen
是一個輔助檔案,記錄當前段的增長編號的
(4)fdx
#FORMAT 整型,4個位元組,3.6.2常量為3,對應00 00 00 03
#DocPosition 每個文件對應一個開始地址,一共有3個文件,每個開始地址佔用一個Long即8個位元組
(5)fdt,fdx建立資料物件呼叫關係
這個過程只是組裝正向資訊的過程,此時,還有沒重新整理到磁碟上
(6)fdt,fdx重新整理磁碟物件呼叫關係
2.tis,tii
tis,tii儲存(詞Term)反向索引資訊,tis儲存詞的資料資訊,tii儲存詞的索引(位置)資訊
tis資料資訊在addDocument已經完成最重要的方向索引結構,在往檔案上刷的時候只是重新排序和合並不同域資訊等處理。 IndexWriter.addDocument | ---DocumentsWriter.updateDocument | ----DocumentsWriterThreadState | ------DocFieldProcessorPerThread.processDocument | ------DocFieldProcessorPerField.processFields 這個方法用於組裝最重要的方向索引結構,這裡有幾點需要了解的地方 #Lucene的反向索引並不傳說中的連結串列的方式儲存的,而是用幾個陣列及輔助資訊儲存的。 #該方法是以域為單位分詞的,也就是說相同的詞在不同的域是分別儲存的,在flush的時候才做合併處理。 反向資訊儲存資料結構是有主儲存結構和輔助結構共同完成的 #主儲存結構有三個陣列,分別是bytePool,charPool,intPool charPool 儲存分詞後的Term資料資訊 bytePool 儲存Term的詞頻及位置資訊,初始化每個詞有10個位元組空間,前5個位元組儲存詞頻資訊,後5個位元組儲存詞位置資訊 intPool和bytePool是配合使用的,每個詞在intPool分配兩個位元組,用於指向bytePool的儲存詞頻和位置資訊的地址, #輔助結構有postingsHash,postingsArray,fieldState等構成. postingsHash 記錄詞的是否出現過, postingsArray 記錄當前此在charPool,bytePool,intPool的位置等資訊 fieldState 記錄當前域的最大詞頻、當前詞頻,該詞在域的postion和offset資訊 通過上面一系列物件的組合就得到了反向索引的初步結構. 通過一個例項展示lucene反向索引是如何儲存的,例如對下面兩條記錄進行索引 id name syno 5159 依雲50ml evian依雲,evian 5160 依雲150ml evian依雲,evian 讀入5159,個物件變化如下: 首先用postionsHash判斷該詞在該域上是否儲存過,5159沒有儲存過 charPool 5,1,5,9, , ?? 5169後面跟一個佔位符,用於詞的分隔 bytePool 0,0,0,0,16,0,0,0,0,16 ?? 前五個位元組儲存該詞的詞頻,第一個位元組儲存這個詞第一次出現的詞頻, 因為只有下一個域也hash到這個詞,才能+1,目前是0,第二組5個位元組用於儲存詞在該域的位置。 intPool 0,6 ?? 0指向該詞在byte寫入的位置,因為5159詞頻沒有發生變化,所以第一個位元組為0, 5159這個詞已經儲存在bytePool[5]的位置上,所以下一個寫入的位置+1變成6 位置儲存的計算是位運算,例如第一個位置0<<1等於0,第二個位置1<<1等於2,以此類推。 通過StandardAnalyzer分析name域 讀取"依" charPool 5,1,5,9, ,依, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,2,0,0,0,16 intPool 0,6,10,16 讀取"雲" charPool 5,1,5,9, ,依, ,雲, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,4,0,0,0,16 intPool 0,6,10,16,20,26 讀取"50ml" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16 intPool 0,6,10,16,20,26,30,36 通過StandardAnalyzer分析syno域 讀取"evian" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,46 讀取"依" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, , ??注意,目前相同詞在不同域是獨立儲存的 bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,2,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,46,50,56 讀取"雲" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,46,50,56,60,66 讀取"evian",這裡變化很關鍵 通過postionsHash發現該域evian儲存過,獲得postingsArray定位到intPool位置,不在寫入evian,intPool[9]++變成了47 charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, , bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,2,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,47,50,56,60,66 讀取"5160" charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, ,5,1,6,0 bytePool 0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,2,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16,0,0,0,0,16,0,0,0,0,16 intPool 0,6,10,16,20,26,30,36,40,47,50,56,60,66,70,76 讀取"依" 通過postingsHash得知該詞在該域儲存過,charPool不需要新增新詞,通過postingsArray定位到intPool位置,將詞頻加1,將postion+=1 charPool 5,1,5,9, ,依, ,雲, ,5,0,m,l, ,e,v,i,a,n, ,依, ,雲, ,5,1,6,0 bytePool 0,0,0,0,16,0,0,0,0,16,1,0,0,0,16,0,2,0,0,16,0,0,0,0,16,0,0,0,0,16,0,0,0,0,16,8,0,0,0,16,0,0,0,0,16,0,2,0,0,16,0,0,0,0,16,2,0,0,0,16,0,0,0,0,16,4,0,0,0,16,0,0,0,0,16,0,0,0,0,16 intPool 0,6,11,17,20,26,30,36,40,47,50,56,60,66,70,76 下面依次類推 有一種情況,就是如果一個詞在域出現的次數大於4次,儲存空間就不夠了,這有一個跳躍表的概念。 &&&至此,反向索引資訊已經初步完成構建。 在寫入tis和tii資訊之前,會先把詞頻(frq)和詞位置(prx)寫入到檔案中 (1)frq儲存term的文件id及詞頻資訊,這裡有兩點需要注意 #frq是以域順序儲存的,例如會先儲存id域所有詞的詞頻,才會儲存name域的詞頻 #文件每個域id是以差值規則儲存的,例如name域有一個term,分別在文件0,1,2出現過1次,Lucene儲存文件id的值分別是0<<1|1 ,1<<1|1 2<<1|1,分別儲存的是1,3,5 如果詞頻大於1,那麼文件id儲存規則為id<<1,並且還有一個位元組儲存頻率 id syno 5159 evian依雲,evian 5160 evian依雲,evian 例如上面的資訊,frq儲存過程如下: #讀入5159, 文件id=0, 0<<1|1 = 1, frq檔案儲存01 #讀取5160, 文件id=1, (1-0)<<1|1 = 3 儲存03 #讀取evian 此時"evian"在文件id=0出現2次,文件id=1出現2次,儲存00 02 01 02 #讀取"依" 此時"依"在文件id=0出現1次,文件id=1出現1次, 儲存01 03 #讀取"雲" 此時"依"在文件id=0出現1次,文件id=1出現1次, 儲存01 03 在lucene儲存詞的順序的時候會通過hash的方式儲存到陣列的位置,上面的儲存方法是正確的,詞的順序會有所不同 (2)prx儲存詞的位置資訊 通frq一樣,prx是以域順序儲存的,例如會先儲存id域所有詞的詞頻,才會儲存name域的詞頻 id syno 5159 evian依雲,evian 5160 evian依雲,evian 例如上面的資訊,prx儲存過程如下: 讀取5159 在文件id=0在第0個位置,prx檔案儲存00 讀取5160 在文件id=1在第0個位置,prx檔案儲存00 讀取evail 在文件id=0,的第一個位置和第三個位置 在id=1第一個位置和第三個位置,所以儲存00 03 00 03 讀取"依" 在文件id=0的第一個位置和id=1的第一個位置,所以儲存01 01 讀取"雲" 在文件id=0的第二個位置和id=1的第二個位置,所以儲存02 02 在IndexWriter.flush方法分別依次往磁碟刷入frq,prx,tis,tii資訊 tis格式如下: FORMAT --- TermCount --- indexInterval --- skipInterval --- maxSkipLevels --- TermInfo ... (Int) (Long) (Int) (Int) (Int) -------- | StartLength --- Length --- DataBytes --- fieldNumber --- docFreq --- freqPointer --- proxPointer (VInt) (VInt) (bytes) (VInt) (VInt) (VLong) (VLong) @FORMAT 當前.tis檔案版本號 3.6.2(-4) @TermCount 詞個數,初次寫入0佔位,在關閉檔案的時候,才寫入真實的個數 @indexInterval 索引間隔(128) @skipInterval 跳過間隔(16) @maxSkipLevels 最大跳躍層數(10) @TermInfo 詞資訊 @#StartLength 開始長度 @#Length 詞所佔的位元組數 @#DataBytes 詞資料資訊 @#fieldNumber 域序號 @#docFreq 該詞在文件出現的頻率 @#freqPointer 詞頻指標,儲存該詞頻指標和最後一個詞頻指標之差 @#proxPointer 位置指標,儲存該詞位置指標和最後一個詞位置指標之差 @#skipOffset 可選項,如果詞頻大於skipInterval,則該位記錄位置偏移 tii格式如下 FORMAT --- TermIndexCount --- indexInterval --- skipInterval --- maxSkipLevels --- TermIndexInfo ... (Int) (Long) (Int) (Int) (Int) -------- | StartLength --- Length --- DataBytes --- fieldNumber --- docFreq --- freqPointer --- proxPointer --- filePointer (VInt) (VInt) (bytes) (VInt) (VInt) (VLong) (VLong) (VLong) @FORMAT 當前.tis檔案版本號 3.6.2(-4) @TermIndexCount 詞索引個數,初次寫入0佔位,在關閉檔案的時候,才寫入真實的個數 @indexInterval 索引間隔 預設(128) @skipInterval 跳過間隔 預設(16) @maxSkipLevels 最大跳躍層數 預設(10) @TermInfo 詞資訊 @#StartLength 開始長度 @#Length 詞所佔的位元組數 @#DataBytes 詞資料資訊 @#fieldNumber 域序號 @#docFreq 該詞在文件出現的頻率 @#freqPointer 詞頻指標,儲存該詞頻指標和最後一個詞頻指標之差 @#proxPointer 位置指標,儲存該詞位置指標和最後一個詞位置指標之差 @#filePointer 域索引檔案指標 frq,prx,tis,tii儲存流程 IndexWriter.doflush | -----DocumentWriter.doFlush | ----DocFieldProcessor.flush | -----DocInverter.flush | -----TermHash.flush | ----- FreqProxTermsWriter.appendPostings 在這個方法依次完成frq,prx,tii,tis寫入。
3.nrm
nrm檔案儲存著所有文件每個域的評分因子,這個因子的演算法需要一些預知識,這裡面評分因子的演算法在評分那篇日誌會細說
.nrm檔案儲存結構: FORMAT ----- perFieldNorm (Int) (byte) @FORMAT nrm版本號,預設{'N','R','M',-1} @perFieldNorm 文件域標準化因子的值 .nrm儲存流程 IndexWriter.doflush | -----DocumentWriter.doFlush | ----DocFieldProcessor.flush | -----DocInverter.flush | ----InvertedDocEndConsumer.flush
4.fnm
儲存了段的一些資料資訊,例如一個段(segement)包含多個域(field),每個域都包含著一些元資料資訊,儲存在.fnm檔案中,.fnm檔案格式如下: FORMAT --- FIELDSIZE ---- fieldInfo .. (VInt) (VInt) ----- | fileldName ---- fieldAttribute (String) (byte) ------ | -- -- -- -- -- -- -- -- (如果索引文件及詞頻) (如果索引文件) (儲存有效負載Payloads) (omitNorms標準化因子) (是否儲存詞向量) (是否被索引)
@FORMAT FNM版本號 -3(3.6.2) @FIELDSIZE 域數量 @fieldInfo 域欄位資訊 @#fieldName 域名稱 @#fieldAttribute 域屬性欄位,一個位元組,8位,每位代表不同的屬性含義,注意:只用了6位
5.segments_n
segments_n儲存段的元資料資訊
6.segments.gen
是一個輔助檔案,記錄當前段的增長編號的