如何设计一个高性能Elasticsearch mapping

  • 前言
  • mapping
    • mapping 能做什么
    • Dynamic mapping
      • dynamic=true
      • dynamic=runtime
      • dynamic=false
      • dynamic=strict
      • 是否可以修改 mapping 中的数据类型
      • 关闭 dynamic mapping
    • Explicit mapping
      • text 类型
      • keyword 类型
      • date 类型
      • numeric 类型
      • boolean 类型
      • 其他类型
  • 总结

前言

在关系型数据库设计当中,表的设计尤其重要,然而关系型数据库更关注的表与表之间的关系,以及表的划分是否合理,而 Elasticsearch 中却更加关注字段类型的设计,一个好的字段类型设计可以更好的利用 Elasticsearch 的搜索分析特性。

mapping

如果说我们想要用好 Elasticsearch,那么就必须要先了解 mapping 什么是 mapping。一句话:mapping是定义如何存储和索引文档及其包含的字段的过程。

mapping 能做什么

前面我们提到,在 Elasticsearch 中,mapping 类似于传统关系型数据库的表结构定义,主要做以下几件事:

  • 定义字段名称和字段类型。
  • 定义倒排索引相关的配置,比如是否被索引,是否可以被分词等。

mapping 可以分为两种:Dynamic mappingExplicit mapping

Dynamic mapping

Dynamic mapping 即:动态映射。动态映射顾名思义就是 mapping 会被动态创建,也就是说我们不需要定义 mapping 就可以往一个索引插入数据,插入索引数据之后,Elasticsearch 会根据插入的数据自动推测数据类型,进而动创建 mapping

比如下面就是往一个不存在的索引 index_001 插入一条数据:

PUT index_001/_doc/1
{"name":"lonely wolf","age": 18,"create_date":"2021-05-19 20:45:11","update_date":"2021-05-23"
}

插入数据之后,执行 GET index_001 来查询一下索引信息:

可以发现,这时候索引已经被自动创建了,而且 age 字段被 Elasticsearch 定义为 long 类型,update_date 被定义为 data 类型,其他两个字段则被推测为 text 类型。

Elasticsearch 中自动映射类型规则可以通过 dynamic 参数进行配置,dynamic 类型有 4 种:

dynamic=true

默认值。当设置为 true 时,一旦有新字段插入文档,则 mapping 会被同步更新。

我们在上面的文档中再插入一个新文档,新文档新增一个 address 字段:

PUT index_001/_doc/2
{"name":"lonely wolf2","age": 20,"create_date":"2021-05-23 11:37:11","update_date":"2021-05-23","address":"广东深圳"
}

然后再查看一下 mapping,可以看到 mapping 已经新增了一个 address 字段,mapping 字段被更新意味着该字段会加入索引:

dynamic=runtime

这个类型和 true 类型非常相似,但是有一个非常大的区别就是,虽然加入新字段也会更新 mapping,但是新加入的字段不会被索引,也就是不会使得索引变大,不过虽然不被索引,但是新加入的字段依然可以被查询,只是查询的代价会更大。所以这种类型一般不建议用在经常查询的条件字段上,而更适合用在一些不确定数据结构的日志类索引中。

修改 dynamic 类型:

PUT index_001/_mapping
{"dynamic":  "runtime"
}

新增一个文档,并加入一个新字段:

PUT index_001/_doc/3
{"email":"123@qq.com"
}

最后询一下 mapping,可以看到字段属性是 runtime,而且类型是 keyword

下表就是自动创建 mapping 时,Elasticsearch 的映射关系:

插入数据类型 dynamic=true dynamic=runtime
null 不会添加任何字段 不会添加任何字段
true 或 false boolean boolean
double float double
integer long long
object object object
string(通过 date 校验) date date
string(通过 numreic 校验) float 或 long double 或 long
string(没有通过 date 或 numreic 校验) text ,并且同时会创建一个 keyword 子域 keyword
array 取决于数组中第一个非 null 值 取决于数组中第一个非 null 值

PS:keyword 表示 不参与分词。

dynamic=false

当设置为 false 时,新加入的字段不会被更新到 mapping,也就是说新字段不会被索引,故以这个字段为条件进行搜索时,无法被搜索到(这一点要注意和 runtime 类型进行区分),不过虽然无法被索引,但是该字段会出现在 _source 中。也就是说该字段不能作为查询条件,但是能被查询出来

接下来我们将 dynamic 修改为 false,并新增一个字段来验证,可以发现新增的字段会出现在 _source 中,但是无法作为条件被查询出来:

dynamic=strict

这种类型最为严格,表示不允许新增一个不在 mapping 中的字段,一旦新增的字段不在 mapping 定义中,则直接报错:

是否可以修改 mapping 中的数据类型

Elasticsearch 中,一旦一个字段被定义在了 mapping 中,是无法被修改的,因为一旦字段被修改了,就会无法被索引(新增字段除外),所以一般我们需要修改索引的话,都会重建索引,并采用 reindex 操作来迁移数据。

关闭 dynamic mapping

可以通过以下两个配置来关闭 dynamic mapping,以下两个属性默认值均为 true,如果需要关闭,则需要修改为 false

action.auto_create_index: true
index.mapper.dynamic: true

Explicit mapping

Explicit mapping 即:显式映射。也就是说这时候我们需要显示的定义字段类型。

Elasticsearch 中支持的字段类型很多,在这里就举一些比较常用的字段类型:

text 类型

这是最常用的一种类型,存储字符串,用于全文索引。当字段被定义为 text 类型时,默认不能用于聚合,排序等操作:

可以看到,用 text 类型字段排序汇报凑,如果想要允许这些操作,可以通过设置 fielddata=true,如下

PUT my-index-011/_mapping
{"properties": {"my_field": { "type":     "text","fielddata": true}}
}

field 字段存储在堆内存中,因为其涉及到的计算比较消耗性能,所以一般不建议设置 fielddata=true,而是通过建立一个 keyword 子域来实现(默认方式):

PUT index_111
{"mappings": {"properties": {"my_field": { "type": "text","fields": {"keyword": { "type": "keyword"}}}}}
}

这种定义方式我们可以将一个字段同时作为 textkeyword 类型使用,如果要用于聚合或者排序等操作则可以使用 字段名.keyword 来作为字段名来进行操作:

keyword 类型

这种类型也非常常用,该字段存储的数据表示一个整体,不可被分词,所以一般不会用来定义大本文的全文检索字段,而是用来存储一些结构化的字符串,比如:id,邮箱,标签等。

keyword 类型一般用于聚合,排序等操作。除此之外,该字段还有两种衍生类型:constant_keywordwildcard

  • constant_keyword:一般用于定义常量类型,比如一个索引中某一个字段全部为同一个值,可以定义为这种类型。
  • wildcard:一般用于模糊匹配查询或者正则匹配查询。

如下就是一个模糊匹配查询的示例(可以配合通配符使用,类似于关系型数据库的 like 操作):

GET index_112/_search
{"query": {"wildcard": {"my_wildcard": {"value": "*quite*lengthy"}}}
}

date 类型

用于定义日期类型,定义日期类型的同时,可以通过 format 来指定日期的格式:

PUT index_113
{"mappings": {"properties": {"date": {"type":   "date","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}}}
}

numeric 类型

Elasticsearch 中提供了比较多的格式用来表示不同长度的数字类型:

数字类型 长度
long 64 位有符号整数。范围:-2 的 63 次方到 2 的 63 次方 -1
integer 32 位有符号整数。范围:-2 的 31 次方到 2 的 31 次方 -1
short 16 位有符号整数。范围:-32768 到 32767
byte 8 位有符号整数。范围:-128 到 127
double 64 位双精度小数
float 32 位单精度小数
half_float 16 位单精度小数
scaled_float 带有缩放因子的浮点数,一般适用于存放金额之类的数据。比如 18.88 元,缩放因子是 100,那么在索引时会被索引为 1888(即:原值 * 缩放因子)
unsigned_long 64 位无符号整数。范围:0 到 2 的 64 次方减 1

定义方式如下所示:

PUT index_002
{"mappings": {"properties": {"number_of_bytes": {"type": "integer"},"time_in_seconds": {"type": "float"},"price": {"type": "scaled_float","scaling_factor": 100}}}
}

boolean 类型

布尔类型比较简单,只有 truefalse 两种:

PUT index_001
{"mappings": {"properties": {"is_published": {"type": "boolean"}}}
}

其他类型

除了上面介绍的一些比较常用的数据类型,Elasticsearch 中还有一些高级数据类型:如 Nested(嵌套类型),地理数据类型,ip 类型等。

总结

Elasticsearch 中支持动态 mapping 和显示 mapping 两种,在使用中有时候可以先插入一条数据到临时索引,等自动生成 mapping 之后,在对现有 mapping 进行修改调整,在字段上尤其要考虑好 text 类型和 keyword 类型的设置,如果需要支持全文搜索和分词搜索,则需要使用 text 类型,需要支持关键字模糊搜索或者聚合排序等操作可以考虑使用 keyword 字段。

如何设计一个高性能Elasticsearch mapping相关推荐

  1. 设计 一个高性能爬虫系统

    资料来源 http://www.xuebuyuan.com/1296711.html 开源中国 http://my.oschina.net/eshijia/blog/136595 最近看了一篇来自纽约 ...

  2. 系统设计——如何设计一个高性能的短链接系统?

    短链系统设计看起来很简单,但如何设计一个高性能短链系统呢,这也是面试中非常常见的一道设计题. 首先,为什么要用短链? 短链跳转的基本原理是什么? 短链生成的几种方法你知道吗? 高性能短链的架构如何设计 ...

  3. 如何设计一个高性能的秒杀系统

    秒杀系统要如何架构,在做技术方案时要注意哪些问题,搞了个秒杀专辑,专门收集秒杀系列文章. 当你去一家公司面试时,很多面试官都会问你如何设计一个高性能秒杀系统.秒杀涉及的技术域从客户端.浏览器.网络.负 ...

  4. 如何设计一个高性能短链系统?

    目录 前言 短链有啥好处,用长链不香吗 短链跳转的基本原理 短链生成的几种方法 1.哈希算法 如何缩短域名 如何解决哈希冲突的问题? 2.自增序列算法 高性能短链的架构设计 总结 前言 今天,我们来谈 ...

  5. 如何设计一个高性能积分系统

    如何设计一个高性能积分系统 功能说明 1:用户签到可以获得积分,需要按照用户维度每天进行用户总积分排行榜 2:需要近实时更新排行榜 3:在积分相同的情况下,需要按照先注册的用户排在前面 4:用户量10 ...

  6. 基于计算机底层基础设计一个高性能的单机管理主机的心跳服务

    大家耐心看下去,你会发现原来计算机基础知识的用处,相信我,你会感触很深刻. 案例需求 ==== 后台通常是由多台服务器对外提供服务的,也就是所谓的集群. 如果集群中的某一台主机宕机了,我们必须要感知到 ...

  7. 如何设计一个高性能CPU?

    任何一种技术都会经历从阳春白雪到下里巴人的过程,就像我们对计算机的理解从"戴着鞋套才能进的机房"变成了随处可见的智能手机.在前面20年中,大数据技术也经历了这样的过程,从曾经高高在 ...

  8. 阿里终面:如何设计一个高性能网关?

    作者:烟味i cnblogs.com/2YSP/p/14223892.html 一.前言 最近在 github 上看了 soul 网关的设计,突然就来了兴趣准备自己从零开始写一个高性能的网关.经过两周 ...

  9. 如何设计一个高性能网关?

    点击上方 "编程技术圈"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 每日英文 Close your eyes. Clear your heart ...

最新文章

  1. mysql获取有哪几种状态_Mysql进阶垫脚石 -- Sql命令的执行状态有哪几种
  2. puppet自动化运维之puppet的资源基础知识
  3. Ubuntu18.04下安装MySQL
  4. python3 ftplib_ftplib — FTP protocol client
  5. HTML项目代码编写规范
  6. Pycharm community配置Django
  7. java远程获取linux文件_Java远程连接操作linux服务器,scp获取文件
  8. 录ppt的时候录光标_光标的使用.ppt
  9. python123平台怎么上课_国内优秀的Python教学平台推荐-python123.io
  10. 批量给excel表中的每行添加表头
  11. Stemming and lemmatization
  12. VSCode连接远程服务器及docker
  13. Image To PDF or XPS V4.2 汉化版,tek2y原创汉化!
  14. 计算机代码画玫瑰,如何用代码画一朵玫瑰花
  15. opencv+python机读卡识别(一)预处理
  16. 使用python的requests库实现书籍比价工具
  17. 软件设计原则之里氏替换原则、依赖倒置原则
  18. 计算机视觉最新进展概览(2021年8月1日到2021年8月7日)
  19. 面对流氓HR,新人该注意什么
  20. input框不可编辑的三种方法

热门文章

  1. 另一个伊甸 VC灵晶效果汇总 23-07-10
  2. android9.0首发机型,安卓9.0正式发布,哪款机型赶上首发?
  3. 从零开始构建gRPC的Go服务
  4. 支持向量机算法之鸢尾花特征分类【机器学习】
  5. mtt s30相当于什么显卡 mtt s30评测 mtts80显卡性能
  6. linux中mysql的库、表和字段的字符集指令总结
  7. python爬虫实例电商_如何用代码爬抓电商数据(附淘宝API调用实例)
  8. 微支付 js-api java 坑王之王!!!
  9. CSS列表(有序,无序,去掉无序列表的点,列表一行显示)
  10. 街斗野战速成教材(功法、技术、心法集合)