数据模型介绍和对比

数据模型

数据模型是一组由符号、文本组成的集合,用以准确的表达信息,达到有效交流、沟通的目的。 —-Steve Hoberman 霍伯曼.数据建模经典教程作者

数据模型设计的元素

实体 Entity
  • 描述业务的主要数据集合
  • 谁、什么、何时、何地、为何、如何

    属性 Attribute
  • 描述实体里面的单个信息

    关系 Relationship
  • 描述实体与实体之间的数据规则

  • 结构规则:1 - N, N - 1,N - N。(一对多、多对一、多对多)
  • 引用规则:电话号码不能单独存在

image.png

传统模型设计:从概念到逻辑到物理

开发者视角:

  1. 概念模型:有哪些实体,比如 内容、组…
  2. 逻辑模型:这些实体具体有哪些特征,比如 联系人有姓名、性别、电话。。。。
  3. 第三范式下的物理模型:原则是数据在库里尽量不可能存在冗余 |
    | 概念模型CDM | 逻辑模型LDM | 物理模型PDM | | —- | —- | —- | —- | | 目的 | 描述业务系统要管理的对象 | 基于概念模型,详细列出所有实体、实体的属性以及关系 | 根据逻辑模型,结合数据库的物理结构,设计具体的表结构,字段列表及主外键 | | 特点 | 用概念名词来描述现实中的实体以及业务规则,如‘联系人’ | 基于业务的描述和数据库无关 | 技术实现细节和具体的数据库类型相关 | | 主要使用者 | 用户需求分析师 | 需求分析师、架构师及开发者 | 开发者、DBA |

模式设计小结

数据模型的三要素:

  • 实体
  • 属性
  • 关系

数据模型的三层深度

  • 概念模型,逻辑模型,物理模型
  • 一个模型逐步细化的过程

    关于JSON文档模型设计

  • 文档模型设计处于是物理模型设计阶段(PDM)

  • JSON文档模型通过内嵌数组或引用字段来表示关系
  • 文档模型设计不遵从第三范式,允许冗余

03-MongoDB模型设计 - 图2

为什么人们都说MongoDB是无模式?

严格来说,MongoDB同样需要概念/逻辑建模
文档模型设计的物理层结构可以和逻辑层类似
MongoDB无模式由来:

  • 可以省略物理建模的具体过程

03-MongoDB模型设计 - 图3

文档模型的设计原则:性能和易用

  1. 性能:Performance
  2. 开发易用:Ease of Development

    关系模型 VS 文档模型

    |
    | 关系数据库 | JSON文档模型 | | —- | —- | —- | | 模型设计层次 | 概念模型
    逻辑模型
    物理模型 | 概念模型
    逻辑模型 | | 模型实体 | 表 | 集合 | | 模型属性 | 列 | 字段 | | 模型关系 | 关联关系、主外键 | 内嵌数组、引用字段 |

MongoDB文档模型设计的误区

  1. 不需要模型设计 ❌
  2. mongodb应该用一个超级大文档来组织所有数据 ❌
  3. MongoDB不支持关联(从3.2版本支持关联,$lookup)或者事务 ❌

    文档模型设计

    03-MongoDB模型设计 - 图4

    第一步:建立基础文档模型

  4. 根据概念模型或者业务需求推导出逻辑模型 -找到对象

  5. 列出实体之间的关系(及基数) -明确关系
  6. 套用逻辑设计原则来决定内嵌方式 -进行建模
  7. 完成基础模型构建

03-MongoDB模型设计 - 图5

一个联系人管理应用的例子

image.png

1-1关系建模:portraits

  • 基本原则:
    • 一对一关系以内嵌为主(把信息作为子文档,总结放入)mongodb支持直接把二进制放在文档中的,不涉及到数据冗余
  • 例外情况
    • 如果内嵌后导致文档大小超过16MB(一个文档不能超过16MB)

image.png

1-N 关系建模:Addresses

  • 基本原则:一对多关系同样是以内嵌为主,用数组来表示一对多,不涉及到数据冗余
  • 例外情况:内嵌后导致文档大小超过16MB,数组长度太大(数万或者更多),数组长度不确定。

image.png

N-N 关系建模:内嵌数组模式

  • 基本原则:不需要映射表,一般用内嵌数组来表示一对多,通过冗余来实现N-N
  • 例外情况:内嵌后导致文档大小超过16MB,数组长度太大(数万或者更多)数组长度不确定

image.png

第二步:根据读写工况细化

03-MongoDB模型设计 - 图10

  • 最频繁的数据查询模式
  • 最常用的查询参数
  • 最频繁的数据写入模式
  • 读写操作的比例
  • 数据量的大小

基于内嵌的文档模型
根据业务需求
使用引用来避免性能瓶颈
使用冗余来优化访问性能

联系人管理应用的分组需求

  1. 用于客户营销
  2. 有千万级别联系人
  3. 需要频繁变动分组(group)的信息,如增加分组及修改名称及描述以及营销状态
  4. 一个分组可以有百万级联系人

image.png

解决方案:Group使用单独的集合

  1. 类似于关系型设计
  2. 用id或者唯一键关联
  3. 使用$lookup来提供一次查询多表的能力(类似关联)

$lookup

  • form: 指定同一数据库中的集合以执行联接。from集合不能分片
  • localField: 本文档中的聚合的数组
  • foreignField:groups文档的字段
  • as:输出的名字

image.png
image.png

联系人的头像:引用模式

  1. 头像使用高保真,大小中5MB - 10MB
  2. 头像一旦上传,一个月不可更换
  3. 基础信息查询(不含头像)和头像查询的比例为9 : 1
  4. 建议:使用引用方式,把头像数据放到另外一个集合,可以显著提升90的查询效率

image.png

* 什么时候该使用引用方式?

  • 内嵌文档太大,数MB或者超过16MB
  • 内嵌文档或数组元素会频繁修改(比如头像,签名等等)
  • 内嵌数组元素会持续增长并且没有封顶

    MongoDB引用设计的限制

  • MongoDB对使用引用的集合之间并无主外键检查

  • MongoDB使用聚合框架的$lookup来模仿关联查询
  • $lookup只支持left outer join (太复杂的关联是没办法完成的)
  • $lookup的关联目标(from)不能是分片表

image.png

第三步:套用设计模式

文档模式:无范式,无思维定式,充分发挥想象力
设计模式:实战过屡试不爽的设计技巧,快速应用
举例: 一个IoT场景的分桶设计模式,可以帮助把存储空间降低10倍,并且查询效率提升数十倍
03-MongoDB模型设计 - 图16

问题:物联网场景下的海量数据处理 - 飞机监控数据

  • 实时对飞机的信息一个记录(航班号、时间戳、位置。。。)

image.png
image.png

解决方案:分桶设计

  • 一个文档:一架飞机一个小时的数据,每一小时存一条

image.png
image.png
image.png

小结:

一个好的设计模式可以显著地:

  • 提升数据读写的效率
  • 降低资源的需求

更多的MongoDB设计模式
image.png

设计模式

问题:大文档,很多字段,很多索引

image.png
image.png

问题;模型灵活了,如何管理文档不同版本?

  • 增加一个版本字段

image.png
image.png
image.png

问题:统计网页点击流量

解决方案:用近似计算
image.png
image.png
image.png

问题:业绩排名,游戏排名,商品统计等精确统计

解决方案:用预聚合字段
$inc递加 添加几个字段递加
image.png
image.png
image.png

MongoDB相关链接

官方文档:https://docs.mongodb.com/manual/mongo/
中文社区:https://mongoing.com
官方中文文档:https://docs.mongoing.com
中文文档:https://www.runoob.com/mongodb/mongodb-databases-documents-collections.html