Elasticsearch基础介绍及原理分析

Elasticsearch介绍

  • ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口操作ES,也可以利用Java API。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
  • Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
  • Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

功能和场景

功能

  1. 分布式的搜索引擎和数据分析引擎
  2. 全文检索,结构化检索,数据分析
  3. 对海量数据进行近实时的处理

场景

  1. 搜索(百度、维基百科等)
  2. 数据分析(日志数据分析,logstash采集日志等)

Elasticsearch基本概念

在这里插入图片描述
上图为我在fat环境下随便查询到的一个文档,可以看到有_index、_type、_id、_version等字段,大家对关系型数据库理解都较为熟悉,我以mysql为例进行对照说明

MySQL数据库
ES索引类型文档
  • _index:soa-info-fat-error-2020.08.17 相当于数据库
  • _type:logs 相当于表
  • _id:AXP4An2QVy6wWtAsJml9 相当于表中唯一表示符(唯一主键)
  • 上图中所有的信息构成一个文档,相当于表中一行数据,es是面向文档的数据库
  • 像traceId、method等这样的相当于表中的列或者说字段。

一个 集群可以包含多个索引(数据库),也就是说其中包含了很多类型(表)。这些类型中包含了很多的文档(行),然后每个文档中又包含了很多的字段(列)。

引出倒排索引

索引一词较为出现评率较高的场景是在关系型数据库的查询中。索引的作用是加快数据查询。以MySQL为例,当一个表中出现亿量单位条数据时,如果通过全表查询时间复杂度是相当高的,因此为了提升查询效率对关键字段建立索引,MySQL中以B+Tree数据结构建立索引。我们假设某表中有10条数据,其中ID为索引字段,数据如下:

IDnameagesexinterests
1zhangsan18malesports, music
2lisi20malefootball,music,movie
3xiaohong18femalemusic,book,sports
4liming21femalepiano,novel
5wangwu20malegame,movie

当MySQL以ID建立索引时,其结构可能如下。在查询id=?时最多查询两次即可。
在这里插入图片描述
现有需求如下:统计男女各有多少人数,统计兴趣有music的有谁,在没有建立索引的情况下需要全表扫描了,时间较高。如果对每个字段建立索引是不现实的,这会加大表维护的代价。因此,可以使用inverted index(倒排索引或者转置索引) 顾名思义,其以内容对数据进行索引。以性别和兴趣为例子,

ageid
18[1,3,…]
20[2,5,…]
21[4,…]
interestsid
sports[1,3,…]
music[1,2,3,…]
movie[2,5,…]

此时统计找到age=18或者interests包含sports,是非常省时的。
以上为提升查询效率的第一步


Term查询优化

像18、20、sports、music、male、female等单个字段叫做term,所有的字段叫term dictionary 。[1,3,…]叫做posting list是一个数组。
如果有大量的term进行存储,如果通过顺序遍历,时间也是非常大的,同样为了加快Term的查询,es将二分法加入到查询term中并且为了提升查询效率引入term index查询和fst压缩技术。
Term index技术实质为trie tree(字典树),上面term没有典型性,现假设有单词abcd,abd,b,bcd,efg,hij利用字典树则建立结果如下所示,红色节点为标记(结束)节点,且有对应term dictionary的指针。这样在查找abcd所对应的id时,步骤为:

  1. 查询字典树
  2. 如果查到标记节点,则定位到term dictionary的offset
  3. 根据term dictionary查询到对应的posting list

注:底层还通过fst对trie tree进行了压缩,使其大小仅为原来的十几分之一
在这里插入图片描述


Posting list

上面讲了对term优化,下面对posting list进行优化。如果ID数组较长,则也需要一定内存,为了尽可能的减少使用

Frame Of Reference

增量编码压缩,将大数变小数,按字节存储。首先posting list是有序的,假设有如下id:73,300,302,332,343,372。采用增量压缩结果如下:可以看到在step2中第n(n>1)个数实际值为前n项相加。在step3中将值按照一定大小分组,在第一组中最大227,用8bit即可,因此3*8bit=3byte,只需要3字节,第二组最大29用5bit,因此只用2字节。这样操作不用每个数字用integer(4字节)存储,大大减少了空间。其实还可以对空间进行压缩。
在这里插入图片描述

bitmap

位图,1byte即可表示8个数字,比如有1,2,3,4,5,6,7,8假如用3bit表示每一位数字,8*3=3byte。而用bitmap可表示为[1,1,1,1,1,1,1,1]。如果是大数可节省更多空间。1亿个连续正整数大约需要12.5m空间(100000000/8/1024/1024)

Roaring bitmaps

bitmap的升级版,上面说了1亿个数字还需要12.5m,随着数据的增长id也在增长,势必带来空间的使用,roaring bitmaps进一步设定规则,它将每个数字除65535,这样将会变成(商,余数)。将商一样的分组,每组的余数作为id,这样每组的id就不会超过65536,而且每组中数字存储也会进行分组,如果数字大于4096就用bitset存储,小于4096就用short存储。如图
在这里插入图片描述
注1 为什么用65536,2^16-1=65535正好为short存储字节数,占用空间少。
注2 为什么每块用4096个数区分阈值,因为每块中最大值为65536,假设里面全部用bit set存储,65536bit/8/1024=8kb,那么假设有4096个数,每个数用short存储 2byte*4096/1024=8k,下面用图对比一下使用空间情况
在这里插入图片描述

转载/参考
https://www.elastic.co/guide/cn/elasticsearch/guide/2.x/index.html
https://www.cnblogs.com/dreamroute/p/8484457.html
https://www.elastic.co/cn/blog/frame-of-reference-and-roaring-bitmaps
es操作官方文档 这是2.x 虽然有些语法变了 但是问题不大
https://www.elastic.co/guide/cn/elasticsearch/guide/2.x/index.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值