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