ES 是一个开源的高扩展的分布式全文检索引擎,它是对开源库 Luence 的封装,提供 REST API 接口
MySQL 更适合数据的存储和关系管理,即 CRUD;而 ES 更适合做海量数据的检索和分析,它可以秒级地从数据库中检索出我们感兴趣的数据
Index 索引
对应 MySQL 中的 db
Type 类型
对应 MySQL 中的 table。每一种类型的数据存放在一起
Document 文档
对应 MySQL 中的 一条记录。保存在某个 index 下,某种 type 的一个数据 document,文档是 json 格式的,每一行对应的列叫属性
字段类型
核心类型
-
字符串
-
text ⽤于全⽂索引,搜索时会自动使用分词器进⾏分词再匹配
-
keyword 不分词,搜索时需要匹配完整的值
-
-
数值类型
-
整型: byte,short,integer,long
-
浮点型: float,half_float,scaled_float,double
-
-
日期类型:date
-
范围类型:integer_range, long_range, float_range,double_range,date_range
-
布尔类型:boolean
-
二进制类型:binary,会把值当做经过 base64 编码的字符串,默认不存储,且不可搜索
复合类型
- 对象:object,可以嵌套对象
- 数组:array
Mapping映射
Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的
动态映射
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而 ES 中不需要定义 Mapping 映射〈即关系型数据库的表、字段等),在文档写入 ES 时,会根据文档字段自动识别类型,这种机制称之为动态映射
动态映射规则如下:
type概念移除
关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用,但 ES 中不是这样的,在 ES 中不同 type 下名称相同的 filed 最终在 Lucene 中的处理方式是一样的
两个不同 type 下的两个 user_name,在 ES 同一个索引下其实被认为是同一个 filed,你必须在两个不同的 type 中定义相同的 filed 映射。否则,不同 type 中的相同字段名称就会在处理中出现冲突的情况,导致Lucene 处理效率下降。去掉 type 就是为了提高 ES 处理数据的效率
-
Elasticsearch 7.x URL中的 type 参数为可选。比如,索引一个文档不再要求提供文档类型
-
Elasticsearch 8.x 不再支持URL中的type参数
-
解决方案:将索引从多类型迁移到单类型,每种类型文档一个独立索引。将已存在的索引下的类型数据,全部迁移到指定位置即可
倒排索引机制
想想看,这个世界上那么多单词,中文、英文、日文、韩文 ... 你每次搜索一个单词,我都要全局遍历一遍,很明显不行。
于是有了排序,我们需要对单词进行排序,像 B+ 树一样,可以在页里实现二分查找。
光排序还不行,你单词都放在磁盘呢,磁盘 IO 慢的不得了,所以 Mysql 特意把索引缓存到了内存。
你说好,我也学 Mysql 的,放内存,3,2,1,放,哐当,内存爆了。
哪本字典,会把所有单词都贴在目录里的?所以,上图:
Lucene 的倒排索引,增加了最左边的一层「字典树」term index,它不存储所有的单词,只存储单词前缀,通过字典树找到单词所在的块,也就是单词的大概位置,再在块里二分查找,找到对应的单词,再找到单词对应的文档列表。