谈谈lucene倒排索引的存储方式(3-3)

            经过谈谈lucene倒排索引的存储方式(3-2)谈谈lucene倒排索引的存储方式(3-1)的分析可知,当有公共前缀的词的数量达到指定阈值时会写入到一个Block中,不过尚未对其中的细节进行分析,现经过给定的输入abc、abcd、abcde、abcdef、abcdf、abcdg、abe、abf、abg、abh,以及参数阈值MIN_BLOCK_SIZE = 3和MAX_BLOCK_SIZE = 4来对倒排索引的构成进一步研究。数组

            当输入abe时因为abcd、abcde、abcdef、abcdf、abcdg以abcd为前缀的个数为5个已经超过MIN_BLOCK_SIZE个数,所以达到写成一个Block的条件,因为MAX_BLOCK_SIZE=4因此对这5个item须要进一步按照MIN_BLOCK_SIZE3个为一组进行拆分,即abcd、abcde、abcdef会写到一个Block(该Block也是一个leafBlock,由于它的元素只有词)中,除了前缀abcd,其他的后缀以及postings元数据(通过压缩)会所有写入到termsOut文件流中,对于该Block有如下重要属性prefix, startFP, hasTerms, isFloor, floorLeadLabel, subIndices,其中prefix表示公共前缀即abcd,startFP表示termsOut文件流指针(经过该指针能够从tim文件中解析出该Block中每一个词的信息),hasTerms表示该块是否包含词(很明显该Block中所有都是词),isFloor为True表示该块因为超过MAX_BLOCK_SIZE个数进行了进一步分块,floorLeadLabel该块中第一个词的第prefixLen个字符(该块为-1),subIndices表示子块的索引(该块没有子块)。而后abcdf与abcdg会一样写入到一个新块中,不过此时prefix记录的是abcdf,floorLeadLabel记录的是f。写完这两个块就得想办法如何能定位这两个Block了:首先这两个块的Floor都为True,先写入第一个块的fp、hasTerm标记和isFloor,再写入剩余Block的个数对每一个Block写入floorLeadLabel(主要用于查询某个词时能够预判,若是不存在就无需加载该块下全部的词),这些信息最终会转换成字节数组而且和前缀abcd一块儿写入FST中,该FST是保存在第一个Block中的,最后将pending列表中的abcd、abcde、abcdef、abcdf、abcdg替换成该Block,因而pending列表中的元素为pendingTerm:abc、pendingBlock:abcd以及新增的pendingTerm:abe。多线程

           继续添加abf、abg、abh,此时pending列表中有6个entry,其中5个term,1个block。最后需将这6个entry按照MIN_BLOCK_SIZE和MAX_BLOCK_SIZE设定的阈值继续分块:首先term:abc、block:abcd、term:abe会组成一个新的Block,其中在写入block:abcd时记录的是block的文件指针,而后term:abf、abg、abh也会造成一个新的Block,最后这两个新的Block会按照前面所述的方式一块儿写入FST中并保存在第一个Block中。至此倒排索引的存储方式算是分析结束了,其实lucene的倒排索引的逻辑视图仍是树状的(最终会以FST的形式保存索引数据因为FST能够共享后缀因此FST是个图,可是它也能够认为是对树的一种优化,咱们能够认为FST是一种共享后缀的前缀树),早期实现的跳跃链表也是树状的,而关系库中经常使用的B树也是树状的,它们在查询的效率以及读写的实时性上有必定的差别性,之后对这三种形式的树进行仔细的分析。后面仍是着重对lucene的索引合并、多线程写入、实时性以及事务性方面进行分析!post

相关文章
相关标签/搜索