最近业务某部分涉及到 ElasticSearch ,工作之余学习了相关使用,但相关文章对于为什么要用 ES 讲得都不是很容易理解,尝试自己自己整理一下。基础使用内容不赘述

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口

全文搜索

ES 主要的使用场景是搜索,以按照名称模糊搜索为例。这个功能如果用 MySQL 实现,我们会这么做( SQL like)

  1. SELECT * FROM user WHERE name like "%key%";

对于某个字段的模糊查询 MySQL 还是能做的,虽然速度会慢一点(原因是索引结构,后面会讲)。但对于多个字段的模糊搜索,MySQL会开始变得复杂。假设需求升级,变成搜索的内容不止包括名称,还包括花名、部门。如果还是用 MySQL 实现,代码逻辑会变成对 name、nickname、dept 三个字段分别进行 like ,然后汇总得到的数据结果。性能更差,如果再加上搜索权重等逻辑,代码会变得更复杂。
而同样的逻辑,使用 es 实现则会简单很多,如下。搜索权重在创建索引时设置 boost 字段即可

  1. GET soa_org_member/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "should": [
  6. {
  7. "match": {
  8. "user.name.raw": "测"
  9. }
  10. },
  11. {
  12. "match": {
  13. "user.profileName.raw": "云"
  14. }
  15. }
  16. ]
  17. }
  18. }
  19. }

搜索速度 -> 倒排索引

ES 文章必定会提到的另一个点是搜索速度快,而快的原因就是因为使用了倒排索引这样一种数据结构。还是以用户表为例。

id name age
5 张三 20
6 李四 30
7 王五 40
8 小李 30

MySQL索引通常是以某个字段(例如 id)作为索引。查到 id 为 6 这条数据的时候,借用一张网图,MySQL B+ 树的索引过程如下:

image.png
普通的查询效率是比较高的,但做模糊查询(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 结构灵活,自由调整。如文本文档等