现在开启lucene倒排索引之词的索引存储之旅也就是对BlockTreeTermsWriter类分析,这是lucene中难啃的骨头之一,为了方便记忆和理解,还有保持内容的跟进,先准备对着代码一步步描述,而前面所有关于lucene的内容都是看完代码再总结的,因此可以想象这块内容的复杂度。

当写入一个词的时候会先写入该词的posting,然后将再写入返回的posting状态信息和词本身。posting的写入过程在谈谈lucene倒排索引的存储方式(一)和(二)中已经说明。

假设minItemsInBlock=3,根据下面的代码谈谈lucene倒排索引的存储方式(3-1)-LMLPHP

当输入abc时:

   prefixStarts=[0,0,0]        pendingSize=1;

当输入abcd时:

   prefixStarts=[0,0,0,1]        pendingSize=2;

当输入abcde时:

   prefixStarts=[0,0,0,1,2]        pendingSize=3;

当输入abe时:

    prefixStarts 从理应的[0, 0, 3, 1, 2]变成[0, 0, 1, 1, 2]        pendingSize=4;

如果只看输入abe时prefixStarts=[0, 0, 3, 1, 2],从输入abc时prefixStarts的变化情况,结合prefixTopSize可以看出prefixStarts下标记录的是公共前缀的长度,值记录的是pending列表中元素的id,通过pending.size–id可以求得公共长度prefixTopSize的长度。例如当输入abe时,从上一个词abcde的最后一个e开始扫描,计算abc、abcd、abcde中与abcde有公共前缀的词的个数为1,然后从d开始计算abc、abcd、abcde与abcd有公共前缀的词的个数为2,以此类推计算abc、abcd、abcde与abc有公共前缀的词个数为3正好达到minItemsInBlock的阈值,所以最终结论是每次写入一个新词时,当已有词列表最长公共前缀达到给定阈值时会写入到一个block中(这里还没具体看代码分析但是从writeBlocks方法可以看出来),为什么是最长公共前缀呢因为在输入abe前以a和ab为前缀的词同样有3个,这样压缩效率没有以abc为前缀的高。下篇分析writeBlocks方法。

09-29 10:33