Su的技术博客

  • 首页
  • 原创
  • 视频
  • Java
  • MySQL
  • DDD
  • 事故复盘
  • 架构方案
  • AI
  • Other
  • 工具
    • AI工具集
    • 工具清单
    • JSON在线格式化
    • JSON在线比较
    • SQL在线格式化
  • 打赏
  • 关于
路很长,又很短
  1. 首页
  2. ElasticSearch
  3. 正文
                           

【数据建模】干货 | 论Elasticsearch数据建模的重要性

2025-05-11 42点热度 0人点赞 0条评论

1、什么是数据模型?

数据模型是抽象描述现实世界的一种工具和方法,是通过抽象的实体及实体之间联系的形式,用图形化的形式去描述业务规则的过程,从而表示现实世界中事务的相互关系的一种映射。
核心概念:

  1. 实体:现实世界中存在的可以相互区分的事务或概念称为实体。
    实体可以分为事物实体和概念实体。例如:一个学生、一个程序员等是事物实体。一门课、一个班级等称为概念实体。

  2. 实体的属性:每个实体都有自己的特征,利用实体的属性可以区别不同的实体。例如。学生实体的属性为姓名、性别、年龄等。

2、数据建模的过程?

数据建模大致分为三个阶段,概念建模阶段,逻辑建模阶段和物理建模阶段。

干货 | 论Elasticsearch数据建模的重要性

2.1 概念建模阶段

概念建模阶段,主要做三件事:

  • 客户交流

  • 理解需求

  • 形成实体

确定系统的核心需求和范围边界,设计实体与实体之间的关系。

在概念建模阶段,我们只需要关注实体即可,不用关注任何实现细节。很多人都希望在这个阶段把具体表结构,索引,约束,甚至是存储过程都想好,没必要!因为这些东西使我们在物理建模阶段需要考虑的东西,这个时候考虑还为时尚早。

概念模型在整个数据建模时间占比:10%左右。

2.2 逻辑建模阶段

逻辑建模阶段,主要做二件事:

  • 进一步梳理业务需求,

  • 确定每个实体的属性、关系和约束等。

逻辑模型是对概念模型的进一步分解和细化,描述了实体、实体属性以及实体之间的关系,是概念模型延伸,一般的逻辑模型有第三范式,星型模型和雪花模型。模型的主要元素为主题、实体、实体属性和关系。
逻辑模型的作用主要有两点。

  • 一是便于技术开发人员和业务人员或者用户进行沟通 交流,使得整个概念模型更易于理解,进一步明确需求。

  • 二是作为物理模型设计的基础,由于逻辑模型不依赖于具体的数据库实现,使用逻辑模型可以生成针对具体 数据库管理系统的物理模型,保证物理模型充分满足用户的需求。
    逻辑模型在整个数据建模时间占比:
    60%—70%左右。

2.3 物理建模阶段

物理建模阶段,主要做一件事:

  • 结合具体的数据库产品(mysql/oracle/mongo/elasticsearch),在满足业务读写性能等需求的前提下确定最终的定义。

物理模型是在逻辑模型的基础上描述模型实体的细节,包括数据库产品对应的数据类型、长度、索引等因素,为逻辑模型选择一个最有的物理存储环境。

逻辑模型转化为物理模型的过程也就是实体名转化为表名,属性名转化为物理列名的过程。

在设计物理模型时,还需要考虑数据存储空间的分配,包括对列属性必须做出明确的定 义。

物理模型在整个数据建模时间占比:20%—30%左右。

例如:客户姓名的数据类型是varchar2,长度是20,存储在Oracle数据库中,并且建立索引用于提高该字段的查询效率。

3、数据建模的意义?

干货 | 论Elasticsearch数据建模的重要性

 

如下图所示:

干货 | 论Elasticsearch数据建模的重要性

 

数据模型支撑了系统和数据,系统和数据支撑了业务系统。

一个好的数据模型:

  • 能让系统更好的集成、能简化接口。

  • 能简化数据冗余、减少磁盘空间、提升传输效率。

  • 兼容更多的数据,不会因为数据类型的新增而导致实现逻辑更改。

  • 能帮助更多的业务机会,提高业务效率。

  • 能减少业务风险、降低业务成本。

举例: 借助logstash实现mysql到Elasticsearch的增量同步,如果数据建模阶段没有设计:时间戳或者自增ID,就几乎无法实现。

4、Elasticsearch数据建模注意事项

干货 | 论Elasticsearch数据建模的重要性

4.1 ES Mapping 设置

干货 | 论Elasticsearch数据建模的重要性

4.2 ES Mapping 字段设置流程图

干货 | 论Elasticsearch数据建模的重要性

4.3 ES 万能Mapping 模板参考

以下的索引 Mapping中,_source设置为false,同时各个字段的store根据需求设置了true和false。

url的doc_values设置为false,该字段url不用于聚合和排序操作。

1PUT blog_index
2{
3  "mappings": {
4    "doc": {
5      "_source": {
6        "enabled": false
7      },
8      "properties": {
9        "title": {
10          "type": "text",
11          "fields": {
12            "keyword": {
13              "type": "keyword",
14              "ignore_above": 100
15            }
16          },
17          "store": true
18        },
19        "publish_date": {
20          "type": "date",
21          "store": true
22        },
23        "author": {
24          "type": "keyword",
25          "ignore_above": 100,
26          "store": true
27        },
28        "abstract": {
29          "type": "text",
30          "store": true
31        },
32        "content": {
33          "type": "text",
34          "store": true
35        },
36        "url": {
37          "type": "keyword",
38          "doc_values":false,
39          "norms":false,
40          "ignore_above": 100,
41          "store": true
42        }
43      }
44    }
45  }
46}


5、不可回避——ES多表关联

实际业务问题:多层数据结构,一对多关系,如何用一个查询查询所有的数据?

比如数据结构如下:帖子--帖子评论--评论用户  3层。

现在需要查询一条帖子,最好能查询到帖子下的评论,还有评论下面的用户数据,一个查询能搞定吗?目前两层我可以查询到,3层就不行了。

如果一次查询不到,那如何设计数据结构?又应该如何查询呢?

目前ES主要有以下4种常用的方法来处理数据实体间的关联关系:

(1)Application-side joins(服务端Join或客户端Join)

这种方式,索引之间完全独立(利于对数据进行标准化处理,如便于上述两种增量同步的实现),由应用端的多次查询来实现近似关联关系查询。

这种方法适用于第一个实体只有少量的文档记录的情况(使用ES的terms查询具有上限,默认1024,具体可在elasticsearch.yml中修改),并且最好它们很少改变。这将允许应用程序对结果进行缓存,并避免经常运行第一次查询。

(2)Data denormalization(数据的非规范化)

这种方式,通俗点就是通过字段冗余,以一张大宽表来实现粗粒度的index,这样可以充分发挥扁平化的优势。但是这是以牺牲索引性能及灵活度为代价的。

使用的前提:冗余的字段应该是很少改变的;比较适合与一对少量关系的处理。当业务数据库并非采用非规范化设计时,这时要将数据同步到作为二级索引库的ES中,就很难使用上述增量同步方案,必须进行定制化开发,基于特定业务进行应用开发来处理join关联和实体拼接。

ps:宽表处理在处理一对多、多对多关系时,会有字段冗余问题,适合“一对少量”且这个“一”更新不频繁的应用场景。

宽表化处理,在查询阶段如果只需要“一”这部分时,需要进行结果去重处理(可以使用ES5.x的字段折叠特性,但无法准确获取分页总数,产品设计上需采用上拉加载分页方式)

(3)Nested objects(嵌套文档)

索引性能和查询性能二者不可兼得,必须进行取舍。嵌套文档将实体关系嵌套组合在单文档内部(类似与json的一对多层级结构),这种方式牺牲索引性能(文档内任一属性变化都需要重新索引该文档)来换取查询性能,可以同时返回关系实体,比较适合于一对少量的关系处理。 

ps: 当使用嵌套文档时,使用通用的查询方式是无法访问到的,必须使用合适的查询方式(nested query、nested filter、nested facet等),很多场景下,使用嵌套文档的复杂度在于索引阶段对关联关系的组织拼装。

(4)Parent/child relationships(父子文档)

父子文档牺牲了一定的查询性能来换取索引性能,适用于一对多的关系处理。其通过两种type的文档来表示父子实体,父子文档的索引是独立的。父-子文档ID映射存储在 Doc Values 中。当映射完全在内存中时, Doc Values 提供对映射的快速处理能力,另一方面当映射非常大时,可以通过溢出到磁盘提供足够的扩展能力。

在查询parent-child替代方案时,发现了一种filter-terms的语法,要求某一字段里有关联实体的ID列表。基本的原理是在terms的时候,对于多项取值,如果在另外的index或者type里已知主键id的情况下,某一字段有这些值,可以直接嵌套查询。具体可参考官方文档的示例:通过用户里的粉丝关系,微博和用户的关系,来查询某个用户的粉丝发表的微博列表。

ps:父子文档相比嵌套文档较灵活,但只适用于“一对大量”且这个“一”不是海量的应用场景,该方式比较耗内存和CPU,这种方式查询比嵌套方式慢5~10倍,且需要使用特定的has_parent和has_child过滤器查询语法,查询结果不能同时返回父子文档(一次join查询只能返回一种类型的文档)。

而受限于父子文档必须在同一分片上,ES父子文档在滚动索引、多索引场景下对父子关系存储和联合查询支持得不好,而且子文档type删除比较麻烦(子文档删除必须提供父文档ID)。

如果业务端对查询性能要求很高的话,还是建议使用宽表化处理的方式,这样也可以比较好地应对聚合的需求。在索引阶段需要做join处理,查询阶段可能需要做去重处理,分页方式可能也得权衡考虑下。

6、小结

本篇文章基于rockybean《Elasticsearch从入门到实践》数据建模篇结合社区精彩问答进行了梳理和扩展,“站在巨人的肩上”,更能体会建模的重要性。

实际业务开发中,务必重视建模,前期在建模方面多下苦功夫、后期的业务系统开发才能水到渠成,更健壮、更有扩展性!

参考:

[1]、rockybean《Elasticsearch从入门到实践》
[2]、官网:http://t.cn/RFKTzBF

[3]、ES建模网站:http://t.cn/RFKT4ST

[4]、ES多表关联讨论:http://t.cn/RFKTixU

[5]、数据建模1:http://t.cn/RFKT9Ug

[6]、数据建模2:http://t.cn/zYmuFii

[7]、数据建模3:http://t.cn/RFKTRpm

推荐阅读:

Elasticsearch实战 | 必要的时候,还得空间换时间!

干货 | Elasticsearch索引生命周期管理探索

探究 | Elasticsearch如何物理删除给定期限的历史数据?

本文仅供学习!所有权归属原作者。侵删!文章来源: 铭毅天下Elasticsearch

 

更多文章:

  1. 设计模式在外卖营销业务中的实践
  2. 殷浩详解DDD系列 第一讲 - Domain Primitive
  3. Spring事务无法生效的11个场景
  4. 如何秒级实现接口间“幂等”补偿:一款轻量级仿幂等数据校正处理辅助工具
  5. 干货 | Elasticsearch 数据建模指南
  6. Java后端18种接口优化技巧
  7. 全链路压测之影子库及ShardingSphere实现影子库源码剖析
  8. DDD系列第五讲:聊聊如何避免写流水账代码
  9. 构建一个布隆过滤器 —— Building a Bloom filter
  10. Routing Elasticsearch架构VI:路由
标签: 数据建模 Nested 搜索引擎 ElasticSearch
最后更新:2025-05-11

coder

分享干货文章,学习先进经验。

打赏 点赞
< 上一篇
广告
文章目录
  • 1、什么是数据模型?
  • 2、数据建模的过程?
  • 3、数据建模的意义?
  • 4、Elasticsearch数据建模注意事项
  • 5、不可回避——ES多表关联
  • 6、小结
最新 热点 推荐
最新 热点 推荐
干货 | 论Elasticsearch数据建模的重要性 马蜂窝消息总线——面向业务的消息服务设计 基于 MySQL Binlog 实现可配置的异构数据同步 视频笔记:Google发布Agent2Agent协议 视频笔记:什么是微服务,为什么是微服务? 视频笔记:什么是AI 智能体? 视频笔记:什么是Flink? 如何秒级实现接口间“幂等”补偿:一款轻量级仿幂等数据校正处理辅助工具
Elasticsearch 使用误区之六——富文本内容写入前不清洗基于 MySQL Binlog 实现可配置的异构数据同步马蜂窝消息总线——面向业务的消息服务设计干货 | 论Elasticsearch数据建模的重要性你可以不用RxJava,但必须得领悟它的思想!如何秒级实现接口间“幂等”补偿:一款轻量级仿幂等数据校正处理辅助工具视频笔记:什么是Flink?视频笔记:什么是AI 智能体?
系统设计 | 如何管理应用系统中的配置? MySQL事务死锁问题排查 JVM GC问题定位排查方法综述 万字长文全面了解学习Netty! 《2023 年度 AI 大事记》 重磅!AI 驱动的 Java 开发框架:Spring AI Alibaba 百度工程师浅谈分布式日志 笔记 | 面试官问我:TCP与UDP的区别

CRUD (1) Event Sourcing (1) graphql (1) id (1) NoSQL (1) quarkus (1) rest (1) RocketMQ (2) Spring Boot (1) zk (1) zookeeper (1) 上下文 (1) 事务消息 (1) 二级缓存 (1) 值对象 (1) 关系数据库 (1) 分布式缓存 (1) 原子性 (1) 唯一ID (1) 商品 (1) 多对多 (1) 子域 (1) 字符集 (1) 客户端心跳 (1) 幂等 (2) 干货 (1) 并发 (1) 应用场景 (1) 应用架构图 (1) 康威定律 (2) 异步复制 (1) 微服务架构 (2) 总体方案 (1) 技术方案 (2) 技术架构 (2) 技术架构图 (1) 技能 (1) 持续集成 (1) 支撑域 (1) 故障恢复 (1) 数据架构图 (1) 方案选型 (1) 日记 (1) 服务发现 (1) 服务治理 (1) 服务注册 (2) 机房 (1) 核心域 (1) 泄漏 (1) 洋葱架构 (1) 消息队列 (5) 源码剖析 (1) 灰度发布 (1) 熔断 (1) 生态 (1) 画图工具 (1) 研发团队 (1) 线程 (2) 组织架构 (1) 缓存架构 (1) 编码 (1) 视频 (18) 读写分离 (1) 贵州 (1) 软件设计 (1) 迁移 (1) 通用域 (1) 集群化 (1) 雪花算法 (1) 顺序消息 (1)

推荐链接🔗
  • AI工具集
  • 工具箱🛠️

COPYRIGHT © 2014-2025 verysu.com . ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

粤ICP备15033072号-2

x