本节书摘来华章计算机《深入理解Elasticsearch(原书第2版)》一书中的第1章 ,第1.1.2节,[美]拉斐尔·酷奇(Rafal Ku) 马雷克·罗戈任斯基(Marek Rogoziski)著 张世武 余洪淼 商旦 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.1.2 Lucene的总体架构
尽管我们可以直接探讨Apache Lucene架构的细节,但是有些概念还是需要提前了解的,以便于更好地理解Lucene的架构,它们包括:
文档(document):索引与搜索的主要数据载体,它包含一个或多个字段,存放将要写入索引的或将从索引搜索出来的数据。
- 字段(field):文档的一个片段,它包括字段的名称和字段的内容两个部分。
- 词项(term):搜索时的一个单位,代表了文本中的一个词。
- 词条(token):词项在字段文本中的一次出现,包括词项的文本、开始和结束的偏移以及词条类型。
Apache Lucene将写入索引的所有信息组织为倒排索引(inverted index)的结构形式。倒排索引是一种将词项映射到文档的数据结构,它与传统的关系数据库的工作方式不同。你可以认为倒排索引是面向词项的而不是面向文档的。我们来看看简单的倒排索引是什么样的。例如,假设我们有一些只包含title字段的文档,如下所示:
- Elasticsearch Server(文档1)
- Mastering Elasticsearch(文档2)
- Apache Solr 4 Cookbook(文档3)
这些文档索引好以后,可简略地显示如下图:
正如你所见,每个词项指向该词项所出现过的文档数。这种索引组织方式允许快速有效的搜索操作,例如基于词项的查询。除了词项本身以外,每个词项有一个与之关联的计数(即文档频率),该计数可以告诉Lucene这个词项在多少个文档中出现过。
每个索引由多个段(segment)组成,每个段写入一次但是查询多次。索引期间,一个段创建以后不再修改。例如,文档被删除以后,删除信息单独保存在一个文件中,而段本身并没有被修改。
多个段将会在段合并(segments merge)阶段被合并在一起。或者强制执行段合并,或者由Lucene的内在机制决定在某个时刻执行段合并,合并后段的数量更少,但是更大。段合并非常耗费I/O,合并期间有些不再使用的信息将被清理掉,例如,被删除的文档。对于容纳相同数据的索引,段的数量更少的时候搜索速度更快。尽管如此,还是需要强调一下:因为段合并非常耗费I/O,请不要强制进行段合并,你只需要仔细配置段合并策略,剩余的事情Lucene会自行完成。
如果你想知道段由哪些文件组成以及每个文件都存储了什么信息,请参考Apache Lucene的官方文档:http://lucene.apache.org/core/4_10_3/core/org/apache/lucene/codecs/lucene410/pa-ckage-summary.html。
更深入地了解Lucene索引
当然,实际的Lucene索引比前面提到的更复杂、更高深,除了词项的文档频率和出现该词项的文档列表外,还包含其他附加信息。在这里我们会介绍一些索引中的附加信息。了解这些信息对我们很有帮助,尽管它们只在Lucene内部使用。
(1)norm
norm是一种与每个被索引文档相关的因子,它存储文档的归一化结果,被用于计算查询的相关得分。norm基于索引时的文档加权值(boost)计算得出,与文档一起被索引存储。使用norm可以让Lucene在建立索引时考虑不同文档的权重,不过需要一些额外的磁盘空间和内存来索引和存储norm信息。
(2)词项向量
词项向量(term vector)是一种针对每个文档的微型倒排索引。词项向量的每个维由词项和出现频率结对组成,还可以包括词项的位置信息。Lucene和Elasticsearch默认都禁用词项向量索引,不过要实现某些功能,如关键词高亮等需要启用这个选项。
(3)倒排项格式
随着Lucene 4.0的发布,Lucene引入了解码器架构,允许开发者控制索引文件写入磁盘的格式,倒排项就是索引中可定制的部分之一。倒排项中可以存储字段、词项、文档、词项位置和偏移以及载荷(payload,一个在Lucene索引中随意存放的字节数组,可以包含任何我们需要的信息)。针对不同的使用目的,Lucene提供了不同的倒排项格式。比如,有一种优化后的格式是专门为高散列范围字段如唯一标识提供的。
(4)doc values
我们前面提到过,Lucene索引是一种倒排索引。不过,针对某些功能,如切面(faceting)或聚合(aggregation),这种倒排索引架构就不是最佳选择。这类功能通常需要操作文档而不是词项,Lucene需要把索引翻转过来构成正排索引才能完成这些功能所需要的计算。基于这些考虑,Lucene引入了doc values和额外的数据结构来进行分组、排序和聚合。doc values存储字段的正排索引。Lucene和Elasticsearch都允许我们通过配置来指定doc values的存储实现方式。可选的存储实现包括基于内存的、基于硬盘的,以及二者的混合。