为什么lucene的文档列表使用跳表而不是bitmap

根本原因

个人感觉,lucene的倒排索引的文档列表,之所以没有选择bitmap,并不是因为bitmap和跳表本身的性能差异,而是因为跳表除了能保存文档列表之外,还能保存其他信息,就比如说该term在文档中出现的次数

因为lucene是为全文检索而生的,全文检索非常关键的一点就是文档的相关度,其中非常重要的一点又是词项出现的频次,一个词项出现在三个文档中,第一个文档出现了3次,剩下两个文档中只出现了1次,那么第一个文档的相关度更高。

所以,如果查出term对应的文档列表之后,能顺便将该term在每个文档中出现的频次顺带拿到,那么后续评分将会非常方便。

对于这点来说,跳表实现起来方便多了,跳表最底层的链表的元素可以携带任意格式的信息;但是bitmap只能保存文档id,如果想要找term出现的次数,还需要再去另一个地方去查询,显然没有那么方便。

倒排索引与评分

倒排索引文件

1
2
3
4
5
6
 12K Oct 10 17:25 _b_Lucene50_0.tip
2.1M Oct 10 17:25 _b_Lucene50_0.tim
172K Oct 10 17:25 _b_Lucene50_0.doc
143K Oct 10 17:25 _b_Lucene50_0.pos
78 Oct 10 17:25 _b.nvm
59 Oct 10 17:25 _b.nvd

其中doc保存的是文档列表以及term在每个文档中出现的频率

可见文档列表文件中除了保存文档id之外,还需要保存term出现的次数。所以用bitmap来作为doc文件的数据结构是不合适的。

评分

评分的时候需要用到上面存储的:

  • doc中的频次
  • nvm和nvd中的字段长度和提升因子

畅享

lucene基于全文检索的需求,文档列表采用了跳表而不是bitmap,但是如果es的使用场景是olap分析,不存在评分,只是过滤查询,那么是不是文档列表使用bitmap更合适,因为bitmap拥有天然的做合并的优势。

druid是一个典型的olap分析引擎,他的维度列的倒排索引的使用的就是bitmap。

上面提到对于keyword字段来说,是只保存docs的,也就是文档列表对应的链表中只有文档id信息,那么这个时候,是不是用bitmap来存储更合适呢?

感觉应该是,因为es在lucene之上,对于filter类型的查询结果对应的文档列表是用bitmap缓存在内存中的,用于后续的多条件查询的时候进行合并,可见bitmap还是有优势的