Elasticsearch 字段膨胀不要怕,Flattened 类型解千愁!

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 1、线上真实案例球友问题:我记得您写过一篇关于建模字段膨胀的问题,对于比如request header response这种动态的对象,是怎么处理来着?进一步反馈:决定升级es高版本了,Flattened 解千愁!主要我们这需求要把接口所有信息都保留,只能这样了。

2、Elasticsarch 字段膨胀

Elasticsearch Mapping 如果不做特殊设置,默认为 dynamic。dynamic 的本质就是:不加约束的动态添加字段。这样对某些日志场景,可能会产生大量的未知字段。字段如果持续激增,就会达到 Elasticsearch Mapping 层面的默认上限,对应设置和默认大小为:index.mapping.total_fields.limit:1000。


我们把这种非预期字段激增的现象或结果称为:字段膨胀。


拿自己线上环境示例,说一下 dynamic 的副作用。在一个实际业务环境,混淆了检索和写入的语法,会导致将检索语句动态认定为新增 Mapping 字段。


当然,如果是非常复杂的大 bool 检索语句,会导致 Mapping 变得非常复杂甚至会出现字段膨胀的情况。

image.png

当然,可行的解决方案就是:dynamic 设置为 false,甚至更为严谨的推荐方式:将 dynamic 设置为 strict。


2.1 解决字段膨胀方案一:dynamic 设置为 false

dynamic 设置为 false 后,新来的非 mapping 预设字段数据可以写入,但是:不能被检索,仅支持 Get 获取文档的方式通过 _source 查看详情内容。


举例如下:

image.png

2.2 解决字段膨胀方案二:dynamic 设置为 strict

dynamic 一旦设置为:strict,会“阻止一切来犯之敌”,一切索引创建阶段指定的 Mapping 字段之外的字段名称都将会报错。


设置为 strict 后,再动态插入数据,会报错如下:


{

 "error" : {

   "root_cause" : [

     {

       "type" : "strict_dynamic_mapping_exception",

       "reason" : "mapping set to strict, dynamic introduction of [cont] within [_doc] is not allowed"

     }

   ],

   "type" : "strict_dynamic_mapping_exception",

   "reason" : "mapping set to strict, dynamic introduction of [cont] within [_doc] is not allowed"

 },

 "status" : 400

}

3、Flattened  类型产生的背景

如前分析,将 dynamic 设置为 false 或者 strict 不是普适的解决方案 ,如日志场景需求如下:


一方面:期望能动态添加字段。strict 过于严谨会导致新字段数据拒绝写入,dynamic 过于松散会字段膨胀。


另一方面:不期望索引字段膨胀。


这就导致同时满足上述两个方面的 Flattend 字段的诞生。


Flattened  中文释义:“压扁、弄平”,实际就是字段扁平化的意思。


当面临处理包含大量不可预测字段的文档时,使用 Flattend 类型可以通过将整个 JSON 对象及其嵌套 Nested 字段索引为单个关键字 keyword 类型字段来帮助减少字段总数。


Flattened 类型的最早发布在:7.3 版本。


4、Flattened 类型解决的根本问题

特定日志场景、电商场景,Elasticsearch Mapping 字段数有时是无法预知的。如果随着新写入数据激增,字段也激增,可能带来的后果是什么呢?


Elasticsearch 必须为每个新字段更新集群状态,并且必须将此集群状态传递给所有节点。由于跨节点的集群状态传输是单线程操作,因此需要更新的字段映射越多,完成更新所需的时间就越长。这种延迟通常大大降低集群性能,有时会导致整个集群宕机。这被称为“ Mapping 爆炸”(mapping explosion)。


这也是 Elasticsearch 从 5.x 及更高版本将索引中的字段数限制为 1000 的原因之一。如果实战业务场景字段数超过 1000,我们必须手动更改默认索引字段限制或者重新考虑架构重构。


修改默认值的方式如下:


PUT record_infos

{

 "settings": {

   "index.mapping.total_fields.limit": 2000

 }

}

Flattened  扁平化字段就是解决:“Mapping 爆炸”问题的。


5、Flattened  类型实战解读

5.1 Flattened  类型真容

千呼万唤始出来,Flattend 真容如下:

image.png

这和 Integer、long、nested、join 等都属于字段类型的范畴。


Flattened  本质是:将原来一个复杂的 Object 或者 Nested 嵌套多字段类型统一映射为偏平的单字段类型。


这里要强调的,不管原来内嵌多少个字段,内嵌多少层,有了 Flattend,一下都打平!!


5.2 基于 Flattened 类型插入数据

基于上面的 Mapping,写入一条数据如下:


PUT demo-flattened/_doc/1

{

 "message": "[5592:1:0309/123054.737712:ERROR:child_process_sandbox_support_impl_linux.cc(79)] FontService unique font name matching request did not receive a response.",

 "fileset": {

   "name": "syslog"

 },

 "process": {

   "name": "org.gnome.Shell.desktop",

   "pid": 3383

 },

 "@timestamp": "2020-03-09T18:00:54.000+05:30",

 "host": {

   "hostname": "bionic",

   "name": "bionic"

 }

}

这时候再查看 Mapping, 如下:

image.png

由于 host 字段设置为:Flattened,其下的:hostname、name 字段都不再映射为特定嵌套子字段。


5.3 更新 Flattened 字段,添加数据

POST demo-flattened/_update/1

{

 "doc": {

   "host": {

     "osVersion": "Bionic Beaver",

     "osArchitecture": "x86_64"

   }

 }

}

再次查看 Mapping,依然“岿然不动”。继续 Flattened 拉平,没有字段扩增,也就不会再有 “Mapping 爆炸”出现。


5.4 Flattened 类型检索

以下两种检索都会召回数据:


GET demo-flattened/_search

{

 "query": {

   "term": {

     "host": "Bionic Beaver"

   }

 }

}

GET demo-flattened/_search

{

 "query": {

   "term": {

     "host.osVersion": "Bionic Beaver"

   }

 }

}

而,如下的检索,则返回结果为空。


GET demo-flattened/_search

{

 "query": {

   "match": {

     "host.osVersion": "bionic beaver"

   }

 }

}

GET demo-flattened/_search

{

 "query": {

   "match": {

     "host.osVersion": "Beaver"

   }

 }

}

为什么呢?


由于使用 Flattened 扁平化类型,Elasticsearch 未对该字段进行分析,因此它只会返回匹配字母大小写且完全一致的结果。


如上检索结果和 keyword 类型检索结果一致。


这也初步暴露出:Flattened 类型的部分缺陷。


5.5 Flattend 类型的不足

每当面临 Flattened 扁平化对象的决定时,在选型 Elasticsearch 扁平化数据类型时,我们需要考虑以下几个关键限制:


Flattened 类型支持的查询类型目前仅限于以下几种:


term


terms


terms_set


prefix


range


match and multi_match


query_string and simple_query_string


exists


Flattened 不支持的查询类型如下:


无法执行涉及数字计算的查询,例如:range query。


无法支持高亮查询。


尽管支持诸如 term 聚合之类的聚合,但不支持处理诸如“histograms”或“date_histograms”之类的数值数据的聚合。


6、小结

Flattened 类型的出现,解决了字段膨胀引起的 Mapping 爆炸问题,如果您的生产环境高于7.3版本,有文章开头类似问题,可以小心求证、大胆尝试这种新类型。


您生产环境使用 Flattened 类型了吗?您有没有遇到过字段膨胀或“Mapping 爆炸”问题,是如何解决的?


欢迎留言说一下您的实战思考!


ps:文章标题灵感起源于球友微信交流,对球友表示感谢!


参考

https://coralogix.com/blog/flattened-datatype-mappings-elasticsearch-tutorial/


https://www.elastic.co/guide/en/elasticsearch/reference/master/flattened.html#flattened

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
4月前
|
PHP
Elasticsearch模糊查询单字段多字段
Elasticsearch模糊查询单字段多字段
40 0
|
4月前
|
Java API iOS开发
Elasticsearch 字段别名 field-alias
Elasticsearch 字段别名 field-alias
75 0
|
2月前
|
自然语言处理 关系型数据库 数据库
ElasticSearch 映射类型及数据类型区分
ElasticSearch 映射类型及数据类型区分
30 0
|
4月前
|
Oracle 关系型数据库 API
实时计算 Flink版产品使用合集之当sink到elasticsearch时,可以指定es的指定字段吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStreamAPI、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
实时计算 Flink版产品使用合集之当sink到elasticsearch时,可以指定es的指定字段吗
|
3月前
|
SQL 安全 数据挖掘
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
Elasticsearch聚合查询用于复杂数据分析,包括统计空值率。示例展示了如何计算字段`my_field`非空非零文档的百分比。查询分为三步:总文档数计数、符合条件文档数计数及计算百分比。聚合概念涵盖度量、桶和管道聚合。脚本在聚合中用于动态计算。常见聚合类型如`sum`、`avg`、`date_histogram`等。组合使用可实现多值统计、嵌套聚合和空值率计算。[阅读更多](https://zhangfeidezhu.com/?p=515)
268 0
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
|
3月前
|
存储 索引
Elasticsearch中父子文档的关联:利用Join类型赋予文档的层级关系
Elasticsearch中父子文档的关联:利用Join类型赋予文档的层级关系
|
3月前
|
存储 索引
Elasticsearch索引之嵌套类型:深度剖析与实战应用
Elasticsearch索引之嵌套类型:深度剖析与实战应用
|
4月前
|
搜索推荐 JavaScript Java
Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?
Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?
58 0
|
4月前
|
SQL Oracle 关系型数据库
实时计算 Flink版产品使用合集之源MySQL表新增字段后,要同步这个改变到Elasticsearch的步骤是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
4月前
|
SQL 关系型数据库 数据库
实时计算 Flink版产品使用合集之将数据写入Elasticsearch时,若Elasticsearch中的字段类型为date,对应的SQL类型应该是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
下一篇
云函数