最近业务某部分涉及到 ElasticSearch ,工作之余学习了相关使用,但相关文章对于为什么要用 ES 讲得都不是很容易理解,尝试自己自己整理一下。基础使用内容不赘述
Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口
全文搜索
ES 主要的使用场景是搜索,以按照名称模糊搜索为例。这个功能如果用 MySQL 实现,我们会这么做( SQL like)
SELECT * FROM user WHERE name like "%key%";
对于某个字段的模糊查询 MySQL 还是能做的,虽然速度会慢一点(原因是索引结构,后面会讲)。但对于多个字段的模糊搜索,MySQL会开始变得复杂。假设需求升级,变成搜索的内容不止包括名称,还包括花名、部门。如果还是用 MySQL 实现,代码逻辑会变成对 name、nickname、dept 三个字段分别进行 like ,然后汇总得到的数据结果。性能更差,如果再加上搜索权重等逻辑,代码会变得更复杂。
而同样的逻辑,使用 es 实现则会简单很多,如下。搜索权重在创建索引时设置 boost
字段即可
GET soa_org_member/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"user.name.raw": "测"
}
},
{
"match": {
"user.profileName.raw": "云"
}
}
]
}
}
}
搜索速度 -> 倒排索引
ES 文章必定会提到的另一个点是搜索速度快,而快的原因就是因为使用了倒排索引这样一种数据结构。还是以用户表为例。
id | name | age |
---|---|---|
5 | 张三 | 20 |
6 | 李四 | 30 |
7 | 王五 | 40 |
8 | 小李 | 30 |
MySQL索引通常是以某个字段(例如 id)作为索引。查到 id 为 6 这条数据的时候,借用一张网图,MySQL B+ 树的索引过程如下:
普通的查询效率是比较高的,但做模糊查询(like 语句)的时候不能走索引,只能全表扫描,性能很差。而 ES 使用的倒排索引的思路,则和上面索引过程相反。
根据名称建立的倒排索引
Term | Posting List |
---|---|
张三 | 5 |
李四 | 6 |
王五 | 7 |
小李 | 8 |
根据年龄建立的倒排索引
Term | Posting List |
---|---|
20 | 5 |
30 | [6,8] |
40 | 7 |
索引的内容是数据本身,通过搜索到的内容去确定数据所在的位置。
例如通过 “李” 搜索时,ES 只需要对第一个表格的 Term 进行检索,发现第 2、4 条数据匹配,进而确定它们的 id 是 6 和 8。
通过年龄 “30” 搜索时,第二个表格搜到第二条记录,并确定有 id 6 和 8 两条数据符合
数据容量 -> 半结构化数据
ES 的一大特点就是号称支持 TB 甚至 PB 级别的数据容量。另外支持 时序、地图等等特殊的数据结构。这些都是源自于 ES 支持的是 半结构化的数据
结构化 | 半结构化 | 非结构化 | |
---|---|---|---|
典型代表 | MySQL | ElasticSearch | MongoDB |
特点 | 结构固定,可以事先定义 | 部分结构固定,但可以调整,如 xml、json | 结构灵活,自由调整。如文本文档等 |