Elasticsearch原理(二):索引存储方式

版权声明:本博客所有文章均为原创,如有转载,请注明原文地址,谢谢!----桃花惜春风 https://blog.csdn.net/xiaoyu_BD/article/details/81806377

Elasticsearch是一个建立在全文搜索引擎库Apache Lucene 基础上的分布式搜索引擎,Lucene最早的版本是2000年发布的,距今已经18年,是当今最先进,最高效的全功能开源搜索引擎框架。

Lucene

Lucene中包含了四种基本数据类型,分别是:

  • Index:索引,由很多的Document组成。
  • Document:由很多的Field组成,是Index和Search的最小单位。
  • Field:由很多的term组成,包括field_name和field_value。
  • Term:由很多的字节组成,可以分词,分词之后每个词即为一个term。term是索引的最小单元。

上述四种类型在Elasticsearch中同样存在,意思也一样。

Lucene中存储的索引主要分为三种类型:

  • Invert Index,即倒排索引。通过term可以快速查找到包含该term的doc_id。如果Field配置分词,则分词后的每个term都会进入倒排索引,如果Field不指定分词,那该Field的value值则会作为一个term进入倒排。(这里需要注意的是term的长度是有限制的,如果对一个Field不采取分词,那么不建议该Field存储过长的值。关于term超长处理)
  • DocValues,即正排索引。采用的是类似数据库的列式存储。对于一些特殊需求的字段可以选择这种索引方式。
  • Store,即原文。存储整个完整Document的原始信息。

下面详细介绍三种类型

Invert Index

倒排索引是lucene的核心索引类型,采用链表的数据结构,倒排索引中的key就是一个term,value就是以doc_id形成的链表结构。

Term      Doc_1      Doc_2
-------------------------
Quick      |               |  X
The         |   X          |
brown     |   X          |  X
dog         |   X          |
dogs       |                |  X
fox          |   X          |
foxes      |                |  X
in            |                |  X
jumped  |   X          |    
lazy        |   X          |  X
leap        |                |  X
over        |   X          |  X
quick      |   X          |
summer  |               |  X
the          |   X          |
------------------------

现在,如果我们想搜索 quick brown ,我们只需要查找包含每个词条的文档:

Term      Doc_1      Doc_2
-------------------------
brown   |   X          |  X
quick    |   X           |
------------------------
Total     |   2           |  1

这里分别匹配到了doc1和doc2,但是doc1匹配度要高于doc2。

倒排索引中的value有四种存储类型:

  • DOCS:只存储doc_id。
  • DOCS_AND_FREQS:存储doc_id和词频(Term Freq)。
  • DOCS_AND_FREQS_AND_POSITIONS:存储doc_id、词频(Term Freq)和位置。
  • DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS:存储doc_id、词频(Term Freq)、位置和偏移(offset)。

DocValues

正排索引类似关系型数据库的存储模式,作用是通过doc_id和field_name可以快速定位到指定doc的特定字段值。DocValues的key是doc_id+field_name,value是field_value。

ES默认会对所有字段进行正排索引,但并不是所有字段都需要DocValues。所以合理配置DocValues可以节省存储空间。DocValues的使用场景一般是:需要针对某个Field排序、聚合、过滤和script。

Store

存储的是Document的完整信息,包括所有field_name和field_value。Store的key是doc_id,value是field_name+field_value。对于上诉中需要聚合和排序的Field并没有开启DocValues的情况,依然可以实现排序和聚合,会从Store中获取要排序聚合的字段值。

Elasticsearch在Lucene基础上的改变

Lucene本身不支持分布式,Elasticsearch通过_routing实现分布式的架构。我们可以通过_routing来实现不同doc分布在不同的Shard上,我们可以自己定义也可以系统自动分配。对于指定_routing的插入和查询,性能上会更好。

Lucene中没有主键索引,并且id是在Segment中唯一。那么Elasticsearch是如何实现doc_id唯一?Elasticsearch中有个系统字段_id,来决定doc唯一。_id是在用户可见层度上的id值,实际上Elasticsearch内部会把_id存储成_uid(_uid =index_type + '#' + _id)。_uid只会存储倒排和原文,目的就是为了通过id可以快速索引到doc。这里需要注意的是,在Elasticsearch6.x版本以后,一个index只支持一个type,这也就意味着_id和_uid概念几乎相同。以后的版本中,Elasticsearch会取消type。

Elasticsearch通过_version字段来保证文档的一致性。更多关于文档的一致性和锁机制的参考:ElasticSearch干货(一):锁机制

Elasticsearch通过_source字段来存储doc原文。这个字段非常重要。Lucene的update是覆盖,是不支持针对doc中特定字段进行修改的。但Elasticsearch支持对特定字段的修改,就是基于_source字段实现的。关于Elasticsearch的update详细内容,参考:ElasticSearch干货(二):index、create、update区别

Elasticsearch通过_field_names字段来判断doc中是否存在某个字段。_field_names的存储形式为倒排,可以快速判断出是否包含某个field_name。

Lucene中Segment一旦创建不可修改。那么Elasticsearch如何实现实时修改并索引数据的呢?详细参考:ElasticSearch原理(三):写入流程

总结:本文介绍了Lucene的存储结构和Elasticsearch如何在Lucene的基础之上实现功能的扩展和优化。

更多:Elasticsearch深入理解专栏

——————————————————————————————————

作者:桃花惜春风

转载请标明出处,原文地址:  

https://blog.csdn.net/xiaoyu_BD/article/details/81806377

如果感觉本文对您有帮助,请留下您的赞,您的支持是我坚持写作最大的动力,谢谢!

猜你喜欢

转载自blog.csdn.net/xiaoyu_BD/article/details/81806377