Elasticsearch原理

基础概念:

Elasticsearch是一个基于Apache Lucene全文搜索引擎开发的分布式的 RESTful 风格的的实时搜索与数据分析引擎,它比Lucene更强大,并且是开源的。官方网站:https://www.elastic.co/cn/

Elasticsearch是面向文档型数据库,一条数据就是一个文档,文档序列化之后是JSON格式,例如一条用户数据:

{
    "name":"tino",
    "age":"25",
    "department":"DC",
    "hobies":[
        "sports",
        "music",
        "movie"
    ]
}

相当于oracle/mysql数据库中的一张user表中的一条记录,这user表有name、age、department、hobies字段,而在Elasticsearch中,这是一个文档,而user则是整个文档的一个类型,Elasticsearch和关系型数据库术语的对照基本上是:

Elasticsearch原理

Elasticsearch 使用的是标准的 RESTful API 和 JSON,它的交互可以通过HTTP请求,也可以通过java API,如果插入一条记录,可以发送一个HTTP请求来实现:

POST /user/add
{
    "name":"tino",
    "age":"25",
    "department":"DC",
    "hobies":[
        "sports",
        "music",
        "movie"
    ]
}

更新和查询也是类似的操作。

Elasticsearch的优点:

1.实现了用于全文检索的倒排索引,实现了用于存储数值数据和位置数据的 BKD 树, 以及用于分析的列存储。

2.将每个字段编入索引,使其可搜索,提高搜索速度。

3.实时分析的分布式引擎,确保故障时仍安全可用。

4.可以在承载了 PB (2的50次方个字节,约为1000个TB)级数据的成百上千台服务器上运行。

5.可处理多种数据类型,数字、文本、地理位置、结构化、非结构化。

倒排索引:

 Elasticsearch最强大的就是为每个字段提供了倒排索引,当查询的时候不用担心没有索引可以利用,什么是倒排索引,举个简单例子:

文档ID

年龄

性别

1

25

2

32

3

25

 每一行是一个文档(document),每个document都有一个文档ID。那么给这些文档建立的倒排索引就是:

年龄的索引:

25

[1,3]

32

[2]

性别的索引:

[1,2]

[3]

可以看到,倒排索引是针对每个字段的,每个字段都有自己的倒排索引,25、32这些叫做term,[1,3]这种叫做posting list,

它是一个int的数组,存储了所有符合某个term的文档id,这时候我们想找出年龄为25的人,就会很快速,但是这里只有两个term,如果有成百上千个term呢,那找出某个term就会很慢,因为term还没有排序,解决这个问题需要了解两个概念:Term Dictionary 和 Term Index。

Term Dictionary

Elasticsearch为了能快速找到某个term,将所有的term进行了排序,然后二分法查找term,类似于上学时候老师教我们的翻新华字典的方式,所以这叫做Term Dictionary,这种查询方式其实和传统关系型数据库的B-Tree的方式很相似,为什么Elasticsearch的查询要快呢。

Term Index

如果说Term Dictionary是直接去二分法翻字典,那么Term Index就是字典的目录页(当然这比我们真的去翻字典目录快多了),假设我们的term如果全是英文单词,那么Term Index就是26个字母表,但是通常term未必都是英文,而可以使任意的byte数组,就算26个英文字符也不一定都有对应的term,比如:

a开头的term只有一个,c开头的term有一百万个,x开头的term一个也没有,这样查询到c的时候又会很慢了。

所以通常情况下erm Index 是包含term的一些前缀的一棵树,例如这样的一个Term Index:

Elasticsearch原理

这样的情况下通过Term Index据可以快速定位到摸个offset(分支的开端),然后以此位置向下查找,再加上FST(Finite-State Transducer,Lucene4.0开始使用该算法来查找Term 在Dictionary中的位置)的压缩技术,将Term Index 缓存到内存中,通过Term Index 找到对应的Term Dictionary的 block,然后再去磁盘直接找到term,减少磁盘的随机读写次数,大大的提升查询效率。(FST在下个章节单独介绍)

Posting List压缩