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 中的位置信息便可在原始文件中将目标数据检索出来。