lucene索引结构整理
一、基础信息
1、索引结构:
-
索引信息元数据:segment_N.
-
段信息元数据:.si
-
正排信息:.fnm .fdx .fdt
-
倒排信息:.tim .tip 与 .doc .pos .pay
-
norm信息:.nvm .nvd
-
doc_value信息:.dvm .dvd
-
term_vector信息:.tvx .tvd
2、存储类型
-
Int8: Byte
-
Int32:4 Byte 无符号int值
-
Int64:8 Byte 无符号int值
-
VInt: 长度在1 到4 Byte之间,支持负数但不建议使用,8 bit中,首位代表是否还有后续Byte 。0111 1111=127 ,1000 0000 0000 0001=128 ,lucene中的或然跟随规则
-
Long : 8 Byte 数值 (也有时候叫 UInt64)
-
VLong: 1到9 Byte之间,规则等同VInt
-
String:utf8编码,前面是一个VInt代表值长度,后面是byte[]
-
Set:首位是一个Int32,代表长度
-
Map:一个Vint,代表长度
-
Packed Array:压缩数组,值域为 0到N ,根据值域计算一个保存每个值必须的 最小长度位数L。一般前面会有一个Vint保存最小长度位数L
二、索引文件结构
1)segment_N:索引信息元数据,主要包含当前索引(目录)中lucene版本信息、段个数、各个段的元数据信息
-
lucene_version (类型VInt)
-
mingSeg_version (类型VInt)
-
version:修改次数 (类型Int64)
-
NameCounter:下一个段的名字 (类型Int32)
-
SegCount:段个数 (类型Int32)
-
SegInfo[SegCount]
-
SegName (类型String)
-
SegID (类型String)
-
SegCodec (类型String)
-
DelGen:修改次数 (类型Int64)
-
DelCount:修改数量 (类型Int64)
-
FieldInfoGen:修改次数 (类型Int64)
-
DocValueGen:修改次数 (类型Int64)
-
2).si:段元数据信息,主要包含应段的lucene版本信息、段内文档数量、是否存为复合文件、以及段的一些动态属性
-
SegVersion: lucene版本号 (类型String)
-
SegSize: 段内文档数 (类型Int32)
-
Files: 段相关索引文件 (类型Set<String>)
-
IsCompoundFile:是否是聚合索引 (类型Int8)
-
Attribute:(类型Map<String,String>)
3)正排信息
.fnm : 域的元数据信息,包括:字段ID、字段名称、字段的IndexOption、Norms选项、DovValue选项、TermVector选项
-
FieldsCount:域的数量(类型VInt)
-
FieldInfo[FieldsCount]
-
FieldName: 字段名 (类型byte)
-
FieldNumber: 字段编号 (类型byte)
-
FieldBits: (类型byte)
-
-1: 启用TermVector
-
-2: 禁用norm
-
-3: 启用Payload信息
-
-
DocValueBits / norms: (类型byte)
-
0:No
-
1:Numeric
-
2:Binary
-
3:Sorted
-
-
IndexOption: (类型byte)
-
0:Not Index
-
1:Docs_Only
-
2:Docs_And_Freqs
-
3:Docs_And_Freqs_And_Poisition
-
4:Docs_And_Freqs_And_Poisition_And_Offsets
-
-
DocValueGen:当前字段的doc_value修改次数
-
FieldBits相关信息:
.fdx:正排数据的索引,用于快速找到指定doc
-
Block [BlockCount]
-
BlockChunks: Block中chunk的数量(类型VInt)
-
-
DocBases: DocID信息
-
DocBase : Block中第一个doc的ID (类型VInt)
-
AvgChunkDoc: fdt文件中每个chunk中doc数量的均值 (类型VInt)
-
BitsPerDocBaseDelta:Packed Array中DocBaseDelta的编码长度,单位bit (类型VInt)
-
DocBaseDelta[BlockChunks]:每个Chunk的docBase和预测docBase的偏移量 (类型Packed Array)
-
-
StartPointers: Doc指针信息
-
StartPointerBase:Block中第一个doc在fdt数据文件中的指针
-
AvgChunkSize:fdt文件中每个chunk数据长度的均值 (类型VInt)
-
BitsPertartPointerDelta
-
StartPointerDelta[BlockChunks]: (类型Packed Array)
-
.fdt:正排数据,包括各文档长度、文档字段数量、文档各字段类型和字段值
-
Chunk[ChunkCount]: 16kb
-
DocBase:chunk中第一个doc的ID (类型VInt)
-
ChunkDocs:chunk中doc数量 (类型VInt)
-
DocFieldCount:文档域的数量
-
if chunkDocs=1,VInt=N
-
else
-
当所有文档的域数相同 bitsRequired=0 VInt=域数量
-
else bitsRequired + packed array 记录每篇文档的域数量
-
-
-
DocLengths:文档域的长度
-
类同DocFieldCount的存储方式
-
-
Doc[ChunkDocs*字段数]
-
FieldNumAndType (类型VLong)
-
Type (后三个bit)
-
0-5:String、Binary、Int、Float、Long、Double
-
-
-
FieldNum:字段ID
-
-
Value :根据Type信息选用不同的数据类型存储
-
-
-
ChunkCount :文件中chunk的个数(类型VInt)
-
#fdx到fdt示意:
-
Block中chunk的个数
-
DocBase信息:
-
Block的第一个BlocalBaseDocId
-
Block中平均每个chunk中保存多少doc: AvgChunkDocs
-
一个数组,保存第n个chunk的第一个docId (ChunkBaseDocId)同BlocalBaseDocId+n*AvgChunkDocs的偏移量
-
-
StartPointer信息
-
基本类似DocBase的存储方式
-
根据DocBase信息找到doc所在的chunk,然后从StartPointer信息里找到对应chunk在.fdt文件中的指针信息
-
4)倒排信息
.tip:倒排词典的前缀索引,会加载在存中,用于快速找到对应词条
-
FSTIndex[NumFields]:FST索引结构,指向文件中对应词的倒排信息位置
-
IndexStartFP[NumFields]:指向对应field的FSTIndex的指针
-
DirOffset:指向IndexStartFP数组起点的指针
.tim:主要包括词条到倒排、倒排跳表、positon、payload/offset信息的映射,以及各个域的基本统计信息
-
NodeBlocks:词和倒排指针信息
-
( InnerNode ) OuterNode
-
EntryCount:term的数量
-
SuffixLength+Suffix:term 前缀信息 (类型VInt +byte[])
-
StatsLength:TermStats数据长度 (类型VInt)
-
TermStats[EntryCount]
-
DocFreq:词的DF信息 (类型VInt)
-
TotalTermFreq:词在所有doc中的TF信息 (类型VLong)
-
-
MetaLength (类型VInt)
-
TermMetadata[EntryCount]
-
DocFilePoint:term在doc文件中的指针 (类型VLong)
-
PosFilePoint: term在pos文件中的位置 (类型VLong)
-
PosVIntBlockFPDelta: .pos文件中,VintBlock的起始位置 。判定block是packed array还是VInt (类型VLong)
-
PayFilePoint:term在payload文件中的位置 (类型VLong)
-
SkipFilePoint:term的跳变信息在pos文件中的位置 (类型VLong)
-
-
-
-
FieldSummarys :各个域的基本统计信息
-
FieldSummary [NumFields]
-
FieldNum:字段ID (类型VInt)
-
NumTerms:域中term的数量 (类型VLong)
-
RootCodeLength +RootCode:指向该field的根block (类型VInt+byte[])
-
SumTotalTermFreq:总TF (类型VLong)
-
SumDocFreq:总DF(不排重,倒排中没出现一次计算一次) (类型VLong)
-
DocCount:总DF (排重,一个DocID计算一次) (类型VInt)
-
LongsSize:记录每个词条需要的平均长度 (类型VInt)
-
MinTerm:该域中最小的词条(字典序) (类型VInt+byte[])
-
MaxTerm:该域中最大的词条(字典序) (类型VInt+byte[])
-
-
.doc :真正的倒排表信息,倒排表中存储着DocID和对应词条的TF信息,并为每个词条保存了跳表结构用于做快速Doc合并。
-
TermInfo[TermCount]
-
PackedBlock[BlockNum]
-
PackedDocDeltaBlock:(类型packed int array )
-
PackeeTermFreqBlock:(类型packed int array )
-
-
VIntBlock
-
DocDelta: (类型VInt)
-
TermFreq :(类型VInt)
-
-
SkipData:跳表数据
-
SkipLevel (类型VInt)
-
SkipDatum[DF/BlockSize ^ (SkipLevel+1)] :
-
DocSkip:doc id (类型VInt)
-
DocFilePointSkip:doc tf信息指针 (类型VLong)
-
PosFpSkip:term的pos信息所在block,在.pos文件中的指针
-
PosBlockOffset:term的pos信息在指定block中偏移
-
PayLength:payload数据长度
-
PayFpSkip:payload数据文件指针
-
SkipChildLevelPoint:下一层、下一级跳表指针
-
-
-
.pos :存储了词的位置信息。
-
PositionInfo[TermCount]
-
PackedPosDeltaBlock[BlockNum]
-
VintBlock:
-
PosDelta:position信息
-
PayloadLength:payload长度
-
PayloadData:payload数据
-
OffsetDelta:offset起始信息
-
OffsetLength:offset长度信息
-
-
这里做了一个策略,PackedPosBlockNum = floor(totalTermFreq/PackedBlockSize)。
剩下的position信息会使用一个VIntBlock进行存储。并且这部分词的payload和offset信息会一起存在这个VIntBlock中。
.pay:存储词的payload信息和offset信息
-
<Pay,Offset>[TermCount]
-
TermPayloadBlock[BlockNum]
-
PayLengthBlock: (类型packed int array )
-
SumPayLength : block中数据总长度 (类型VInt)
-
PayData: (类型byte)
-
-
TermOffsetBlock[BlockNum]
-
PackedOffsetStartDeltaBlock: (类型packed int array )
-
PackedOffsetLengthDeltaBlock: (类型packed int array)
-
-
# tim到倒排数据:
5)字段长度规约
.nvm:
-
Entry[NumFields]
-
FieldNumber:字段编号 (类型VInt)
-
BytesPerValue:指定字段压缩后每个值得长度 (类型Int8)
-
offset:指定字段数据偏移
-
.nvd:
-
Data:(类型byte[])
6)doc_value数据
.dvm .dvd (TODO)
7)文档向量数据
.tvx:文档词向量数据的索引,用于快速找到指定doc
-
Block [BlockCount]
-
BlockChunks
-
DocBases: DocID信息
-
DocBase
-
AvgChunkDoc
-
BitsPerDocBaseDelta
-
DocBaseDelta
-
-
StartPointers: Doc指针信息
-
StartPointerBase
-
AvgChunkSize
-
BitsPertartPointerDelta
-
StartPointerDelta
-
-
.tvd: 存储了各个doc的域的数量、各个域的term_vector策略信息,以及从存储各个doc的词列表,及每个词的position、offset、payload信息
-
Chunk[ChunkCount] : 16kb
-
DocBase
-
ChunkDocs
-
DocNumFields [ChunkDocs]:每个doc的字段数量 (类型Packed Array)
-
FieldNumDelta [TotalDistinctFieldNums]:chunk中字段的unique count值(排重总数) (类型Packed Array)
-
FieleNumOffset [TotalFieldNums]:chunk中字段的count值 (不排重总数) = sum (DocNumFields [ChunkDocs]) (类型Packed Array)
-
Flags
-
Bit :值为1时说明所有文档中,相同字段的term_vector选项是相同的。否则,说明不同文档中相同字段的term_vector选项不同。 (类型bit)
-
if Bit=1 则 Flag[TotalDistinctFieldNums]
-
if Bit=1 则 Flag[TotalFieldNums]
-
Flag:3个bit
-
第1个bit:是否存position
-
第2个bit:是否存offset
-
第3个bit:是否存payload
-
-
-
-
FieldTermNums [TotalFieldNums]: TotalTerms=sum of FieldTermNums [TotalFieldNums]
-
TermLengths
-
PrefixLength [TotalTerms]
-
SuffixLength [TotalTerms]
-
-
TermFreqsMinus1 [TotalTerms]: (类型Packed Array)
-
-
PositionDelta [TotalPosition] : TotalPosition=sum of TermFreqs[TotalTerms] (类型Packed Array)
-
StartOffsets [TotalPosition] : 假设所有字段都存offset (类型Packed Array)
-
PayloadLentgh [TotalPosition]: 假设所有字段都存Payload (类型Packed Array)
-
FieldTermsAndPayLoads [TotalFieldNums]
-
Term [TotalPosition] :(类型byte[])
-
Payload [TotalPosition]:(类型byte[])
-
-
ChunkCount
8)文档删除数据
.liv:存储了被删除doc的id,使用位图形式,并以D-Gaps方式压缩
三、压缩/加速
1)fdx 估值偏移: Block/Chunk压缩
#fdx到fdt示意图:
-
Block中chunk的个数
-
DocBase信息:
-
Block的第一个BlocalBaseDocId
-
Block中平均每个chunk中保存多少doc: AvgChunkDocs
-
一个数组,保存第n个chunk的第一个docId (ChunkBaseDocId)同BlocalBaseDocId+n*AvgChunkDocs的偏移量
-
-
StartPointer信息
-
基本类似DocBase的存储方式
-
根据DocBase信息找到doc所在的chunk,然后从StartPointer信息里找到对应chunk在.fdt文件中的指针信息
-
2)倒排表的数据格式(差值压缩)
-
若设置不存储TF,只需要存储文档号,则每个block第一个doc存储真实dodId,后续doc存储同前一个docId之间的差值
-
当设置存放TF时,规则为,当TF=1,则DocDelta=2* DocDelta+1,TF不再单独存储。若TF!=1,则存放方式为<DocDelta差值*2,TF>
示例:
docId=5的文档中词出现1次,doc=8的文档中,词出现3次
若设置不存储TF:
则存放方式为: 5,3
若设置存储TF:
则存放方式为: 11,6,3。 (或然跟随规则)
奇数代表TF=1,DocId=(DocDelta-1)/2
偶数代表DocId=DocDelta/2+ lastDocId ,TF 随后存储
3)倒排表快速查找(跳表)
-
lucene中跳变的interval等于BlockSize=128
#跳表到数据示意图:
4).liv 文件的DGaps结构
.tvd 词频 blocks of 64 packed ints:
-
MinValue
-
Ints:解压时要加上MinValue
-
5)数值型及日期型数据
-
原始的数值型存储方式,字典树--区间倒排加速
默认情况下int、double、float等数字类型precisionstep为4,就是按4位二进制进行分割
-
k-d tree
四、索引拓展
1)索引数据抛弃:减少召回 非精确的topN召回
-
idf过滤:可以理解一种停用词过滤
-
胜者表:对每个词保留k个胜者文档 (超过k的文档,我们认为它对总分的影响可以忽略)
-
层次型索引:高端表(全局胜者表) + 低端表(其他文档)
按idf值分层,第一层idf>30%(或分>20等),第二层idf>60%(或分>10)
2)前缀后缀索引
-
正向字典树+反向字典树取交集
-
轮排索引
-
hello
-
hello$-》1
-
ello$h—》1
-
llo$he
-
lo$hel
-
o$hell->1
-
$hello
-
-
he*o
-
he*o$
-
o$he*
-
-
*llo
-
*llo$
-
llo$*
-
-
参考资料:
lucene5.5索引结构 https://elasticsearch.cn/article/86
lucene4.5索引结构 http://blog.csdn.net/liweisnake/article/details/10956645
lucene4.7索引结构 https://my.oschina.net/MrMichael/blog/220961
lucene的一些数据结构:FST、压缩、变长数据类型、跳表等 http://blog.csdn.net/liweisnake/article/details/10348969
lucene4.x词典的设计(一) http://www.cnblogs.com/forfuture1978/p/3940965.html
lucene4.x倒排表的设计格式(二) http://www.cnblogs.com/forfuture1978/p/3944583.html
lucene4.x Dictionaru和index文件(FST详细 三) http://www.cnblogs.com/forfuture1978/p/3945755.html
lucene4.x索引文件格式:
http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623597.html
http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623599.html
http://www.cnblogs.com/forfuture1978/archive/2010/02/02/1661436.html
lucene索引结构彩图: http://blog.itpub.net/28624388/viewspace-766026/
完整lucene文档: https://www.cnblogs.com/2018/p/5809548.html Lucene的分析资料【转】 - 2012 - 博客园【内部链接】
lucene索引结构系列 http://so.csdn.net/so/search/s.do?q=lucene&t=blog
lucene4.8源码分析(含详细索引分析): http://www.cnblogs.com/rcfeng/category/659593.html
https://blog.csdn.net/zteny/article/details/84627990 doc_values索引结构
https://www.cnblogs.com/forfuture1978/p/3945755.html
http://www.bubuko.com/infodetail-378415.html doc_value文件详解
https://blog.csdn.net/conansonic/article/details/51966713 doc_value/norm写入过程详解
https://blog.csdn.net/jediael_lu/article/details/34433641