ES 分享
一. 建立倒排索引的认识
倒排索引是一种索引方法,用来存储全文搜索下某个单词在文档中的位置映射。
以古诗问答为例来理解倒排索引:
- 问:说出带"前"字的古诗词
- 问:背一下李白的《静夜思》——
窗前明月光,疑是地上霜 - 背诗的方式:按书中排列顺序,先记诗名再记内容

具象化到关系库模型:

在脑子中形成的索引是这样的:

建立了 name 的索引后,根据 name 找 content 就会很快(SELECT * FROM 古诗 WHERE name = '静夜思'),但反过来查包含某字的诗就变成全表扫描(SELECT name FROM 古诗 WHERE content LIKE '%前%')。
如果以"前"字作为索引,则可以解决这个问题:

但整首 20 字的古诗每个字都适合做索引,光唐诗就有 5 万多首,全部建索引不现实。由于已经可以通过诗名回忆整首诗,所以只需索引到诗名即可:

多首诗的情况:

以上就是倒排索引的入门讲解。
补充:
- ES 默认对全部字段建立索引,如古诗表中
name、author都可以是索引 - 倒排索引的概念源自搜索引擎,最早在 Lucene 中被广泛认知和使用,ES 是在 Lucene 基础上的封装
二. 倒排索引的内部结构详解
Term
在古诗示例中,map 的 key 所代表的就是一个 term(词条)。
Postings List
{静夜思, 望庐山瀑布} 是 "前" 这个 term 所对应的列表。由于整型数字可以被高效压缩(MySQL 也推荐用数字作为 id,同样原因),ES 会将文档转化为唯一的整型 id。
Postings List 就是一个 int 数组,存储所有符合某个 term 的文档 id:

Term Dictionary
可以理解为一本新华字典,存储所有 term。Elasticsearch 将所有 term 排序后用二分法查找——这就是 Term Dictionary。
Term Dictionary 存在内存还是硬盘?硬盘 IO 效率太低,必须放内存。但如果 term 太多(ES 对所有字段默认建索引),直接全部放内存不现实,于是有了 Term Index。
Term Index
类似字典的索引页,记录以各字母开头的 term 在哪一页。Term Index 是一棵树,不包含所有 term,只包含 term 的一些前缀及其与 Term Dictionary block 的映射关系。结合 FST(Finite State Transducers)压缩技术,可以将 Term Index 缓存到内存中。从 Term Index 定位到 Term Dictionary 的 block 位置后,再去磁盘查找具体 term,大大减少了磁盘随机读次数。
三. 结合生产实践讲使用
- ES 是一个分布式存储的搜索和分析引擎
- ES 对外暴露了大量 API,掌握这些 API 就相当于"会用" ES
- ES 7 之后的数据类型支持:

- ES 与 MySQL 的概念对比(
type在 8.0 中已完全删除):

ES 支持两种基本检索方式:Query DSL 和 REST API
以生产日志告警为例,ES 与 MySQL 对比:
ES(Query DSL):查询过去 10 分钟的错误日志
1 | GET prod-sopei-20211007/_search |
MySQL 等价写法:
1 | SELECT * FROM `prod-sopei-20211007` |
其他增删改查操作由于 ES 内容较多,不在此一一概述。