Elasticsearch是什么?
Elasticsearch是一个基于文档的NoSQL数据库,是一个分布式、RESTful风格的搜索和数据分析引擎,同时也是Elastic Stack的核心,集中存储数据。Elasticsearch、Logstash、Kibana经常被用作日志分析系统,俗称ELK。
说白了,ES就是一个数据库,搜索效率很高(但是插入更新较慢,因为要分词,建索引)。速度快,还可以进行分词,非常适合做搜索,例如商城的商品搜索。
而且它是nosql的,数据格式可以随便造。Elasticsearch还为我们提供了丰富的RESTful风格的API,写代码的成本极低。最后它支持分布式,高性能(搜索快),高可用(某些节点宕机可以接着用),可伸缩(可以方便的增加节点,解决物理内存上线问题),适合分布式系统开发。
Elasticsearch的基本概念
ES是一个搜索引擎,也是一种数据库,为了便于理解,与mysql做一下比较。
| Elasticsearch | Mysql |
|---|---|
| 文档(Document) | 记录(行) |
| 字段(Field) | 属性(列) |
| 类型(Type) | 表 |
| 索引(Index) | 数据库 |
Elasticsearch是基于文档的,就是因为记录元素(被搜索的最小单位)是文档
{
"email": "test.com",
"first_name": "Test",
"last_name": "SmithTest",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}
文档格式看起来很像Json。email、first_name等等就是Filed
标题Elasticsearch为什么这么快
首先,我们知道mysql底层数据结构使用的是B+Tree,这种B+Tree,将搜索时间复杂度变成了logN,已经很快了,我们Elasticsearch要比它还快。Elasticsearch是怎么做的呢?
首先储存结构要优化,然后再提高下和磁盘的交互效率。
1.索引结构
ES采用了一种名为倒排索引的索引结构。
传统关系数据库中,我们经常根据主键创建索引,然后根据主键进行查询到整个记录的数据。这种情况叫做正排索引
| id(文档编号) | name | age |
|---|---|---|
| 1 | kate | 24 |
| 2 | tom | 24 |
| 3 | kate | 29 |
| 4 | kate | 26 |
| 5 | tom | 29 |
按照正排索引,根据主键我们可以很轻松的找到想要查询的记录,但是如果想要查询某一字段在哪些记录中出现过,就需要遍历整个表,这个操作十分耗时,效率也低,如果把每个字段所有可能存在的值都拿出来放到一个列表中,然后进行查找,就会大大加快速度。
按照这个思想,出现了倒排索引这个概念。
ElasticSearch会为每个属性创建一个索引树,如下所示
| Term | Posting List |
|---|---|
| kate | 1,3,4 |
| tom | 2,5 |
| Term | Posting List |
|---|---|
| 24 | 1,2 |
| 26 | 4 |
| 29 | 3,5 |
以上的索引树就叫做倒排索引,每个Filed字段对应着一组Term,每个Term后面跟着的id(还记着吗,这个主键是文档id,用户不指定就会自动生成,所以一定存在)就是Posting List,它是一组id,有了id再去磁盘中对应的文档就非常快了。
自然而然的想到,如果Term能够排序,再采用二分查找,那么速度会更快,和B±tree一样。
时间复杂度为LogN。这个有序的Term组就是Term Dictionary。
可是问题又来了,比如说数据库中有name前缀为A的同学1000万个,前缀为Z的同学有3个,我要查前缀为Z的同学,那二分查找不也很多次吗,
所以,Elasticsearch把每个开头的地方标记一下,拿出来,再放到一颗树里,速度不是就快了嘛。
这棵树就是Term Index。Term Index前缀不一定是第一个字符,比如A、Ab、Abz,这种都可以在
Term Index树里。并且Term Dictionary可能会太大,会被放到磁盘中,避免内存占用太多。

TIPS.当使用一个关键词在es中进行检索时,其流程大致应该是这样的:
1.首先通过在内存中的 Term Index 查询出以j打头的Term在Term Dictionary字典文件中的哪个位置(这个位置可以是一个文件指针,可能是一个区间范围)
2.紧接着在将这个位置区间中的所有 Term 取出,由于已经排好序,便可通过二分查找快速定位到具体位置;这样便可查询出 Posting List。
3.最终通过 Posting List 中的位置信息便可在原始文件中将目标数据检索出来。