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

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 1、什么是数据模型?数据模型是抽象描述现实世界的一种工具和方法,是通过抽象的实体及实体之间联系的形式,用图形化的形式去描述业务规则的过程,从而表示现实世界中事务的相互关系的一种映射。

image.png

链接

实体:现实世界中存在的可以相互区分的事务或概念称为实体。

实体可以分为事物实体和概念实体。例如:一个学生、一个程序员等是事物实体。一门课、一个班级等称为概念实体。


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


2、数据建模的过程?

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

image.png

2.1 概念建模阶段

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


客户交流

理解需求

形成实体

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

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

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


2.2 逻辑建模阶段

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


进一步树立业务需求,

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

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

逻辑模型的作用主要有两点。


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

二是作为物理模型设计的基础,由于逻辑模型不依赖于具体的数据库实现,使用逻辑模型可以生成针对具体 数据库管理系统的物理模型,保证物理模型充分满足用户的需求。

逻辑模型在整个数据建模时间占比:60—70%左右。

2.3 物理建模阶段

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


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

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

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

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


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

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


3、数据建模的意义?

如下图所示:

image.png

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

一个好的数据模型:


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

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

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

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

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

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


4、Elasticsearch数据建模注意事项image.png

4.1 ES Mapping 设置

image.png

4.2 ES Mapping 字段设置流程图

image.png

4.3 ES 万能Mapping 模板参考

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

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


PUT blog_index

{

 "mappings": {

   "doc": {

     "_source": {

       "enabled": false

     },

     "properties": {

       "title": {

         "type": "text",

         "fields": {

           "keyword": {

             "type": "keyword",

             "ignore_above": 100

           }

         },

         "store": true

       },

       "publish_date": {

         "type": "date",

         "store": true

       },

       "author": {

         "type": "keyword",

         "ignore_above": 100,

         "store": true

       },

       "abstract": {

         "type": "text",

         "store": true

       },

       "content": {

         "type": "text",

         "store": true

       },

       "url": {

         "type": "keyword",

         "doc_values":false,

         "norms":false,

         "ignore_above": 100,

         "store": true

       }

     }

   }

 }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

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]、官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html

[3]、ES建模网站:https://hackolade.com/help/Elasticsearch.html

[4]、ES多表关联讨论:https://elasticsearch.cn/question/4655

[5]、数据建模1:https://www.zhihu.com/question/266716340

[6]、数据建模2:http://czmmiao.iteye.com/blog/1826904

[7]、数据建模3:https://zhuanlan.zhihu.com/data-analyst-improvement


image.png

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
3月前
|
存储 搜索推荐 数据建模
Elasticsearch 的数据建模与索引设计
【9月更文第3天】Elasticsearch 是一个基于 Lucene 的搜索引擎,广泛应用于全文检索、数据分析等领域。为了确保 Elasticsearch 的高效运行,合理的数据建模和索引设计至关重要。本文将探讨如何为不同的应用场景设计高效的索引结构,并分享一些数据建模的最佳实践。
135 2
|
数据建模 关系型数据库
Elasticsearch之数据建模实战通过应用层join实现用户与博客的关联
Elasticsearch之数据建模实战通过应用层join实现用户与博客的关联
|
存储 JSON 数据建模
Elasticsearch数据建模实战之基于nested object实现博客与评论嵌套关系
Elasticsearch数据建模实战之基于nested object实现博客与评论嵌套关系
Elasticsearch数据建模实战之祖孙三层数据关系建模以及搜索实战
Elasticsearch数据建模实战之祖孙三层数据关系建模以及搜索实战
Elasticsearch数据建模实战之对文件系统进行数据建模以及文件搜索实战
Elasticsearch数据建模实战之对文件系统进行数据建模以及文件搜索实战
|
数据建模 关系型数据库
白话Elasticsearch60-数据建模实战_Join datatype 父子关系数据建模
白话Elasticsearch60-数据建模实战_Join datatype 父子关系数据建模
62 0
|
数据建模
白话Elasticsearch59-数据建模实战_ Nested Aggregation/ Reverse nested Aggregation对嵌套的博客评论数据进行聚合分析
白话Elasticsearch59-数据建模实战_ Nested Aggregation/ Reverse nested Aggregation对嵌套的博客评论数据进行聚合分析
94 0
|
存储 JSON 数据建模
白话Elasticsearch58-数据建模实战_基于nested object实现博客与评论嵌套关系
白话Elasticsearch58-数据建模实战_基于nested object实现博客与评论嵌套关系
79 0
|
数据建模 索引
白话Elasticsearch57-数据建模之实现悲观锁并发控制的三种方式(未成功)
白话Elasticsearch57-数据建模之实现悲观锁并发控制的三种方式(未成功)
97 0
|
自然语言处理 数据建模 索引
白话Elasticsearch56-数据建模之 Path Hierarchy Tokenizer 对文件系统进行数据建模以及文件搜索
白话Elasticsearch56-数据建模之 Path Hierarchy Tokenizer 对文件系统进行数据建模以及文件搜索
58 0