文章目录

  • mongodb数据模型设计
  • 一、基础:关系模型和文档模型
  • 二、数据模型设计
  • 数据模型设计的基础
  • 数据模型设计
  • 三、MongoDB文档模型设计的三个误区
  • 四、如何考虑MongoDB 文档模式设计的基本策略呢?
  • 内嵌模式 EMBEDDED DOCUMENTS
  • 引用模式 REFERENCED DOCUMENTS
  • 数据建模设计最佳实践
  • 五、 其他
  • MongoDB覆盖索引查询
  • MongoDB 使用 count 带来的分页问题与应对措施
  • 参考


mongodb数据模型设计

一、基础:关系模型和文档模型

mongodb分布架构 mongodb 模型_数据库

文档模型的优点:

读写效率高-由于文档模型把相关数据集中在一块,在普通机械盘上读数据的时候不用花太多时间去定位磁头,因此在IO性能上有先天独厚的优势;

动态模式-文档模型支持可变的数据模式,不要求每个文档都具有完全相同的结构。对很多异构数据场景支持非常好;

二、数据模型设计

数据模型设计的基础

数据模型设计
mongdb 官网说明:https://mongoing.com/docs/core/data-model-design.html

  • 实体Entity
  • 属性Attribute
  • 关系Relationship
    1-N,N-1,N-N

mongodb分布架构 mongodb 模型_数据_02


概念模型–>逻辑模型–>物理模型,建模的过程是一个逐步深化的过程!

对于文档数据库,大部分情况下,我们一般直接模拟建模即可~

数据模型设计

数据模型设计
mongdb 官网说明:https://mongoing.com/docs/core/data-model-design.html

内嵌式数据模型

在MongoDB里面,你可以把相关的数据包括在一个单个的结构或者文档下面。这样的数据模式也叫做 “非规范化” 模式,它充分利用了MongoDB的灵活文档格式的功能。以下图为例:

mongodb分布架构 mongodb 模型_nosql_03


内嵌数据可以让应用程序把相关的数据保存在同一条数据库记录里面。这样一来,应用程序就可以发送较少的请求给MongoDB数据库来完成常用的查询及更新请求。

一般来说,下述情况建议使用内嵌数据:

  • 数据对象之间有 “contains” (包含) 关系。 参见 一对一关系建模:内嵌文档模型。
  • 数据对象之间有一对多的关系。 这些情况下 “多个”或者子文档会经常和父文档一起被显示和查看。请参见 一对多关系建模: 内嵌文档模型。

通常情况下,内嵌数据会对读操作有比较好的性能提高,也可以使应用程序在一个单个操作就可以完成对数据的读取。 同时,内嵌数据也对更新相关数据提供了一个原子性写操作。

规范化数据模型

规范化数据模型指的是通过使用 引用 来表达对象之间的关系。

mongodb分布架构 mongodb 模型_mongodb分布架构_04


一般来说,在下述情况下可以使用规范化模型:

  • 当内嵌数据会导致很多数据的重复,并且读性能的优势又不足于盖过数据重复的弊端时候。
  • 需要表达比较复杂的多对多关系的时候。
  • 大型多层次结构数据集。

引用比内嵌要更加灵活一些。 但客户端应用必须使用二次查询来解析文档内包含的引用。换句话说,对同样的操作来说,规范化模式会导致更多的网络请求发送到数据库服务器端。

三、MongoDB文档模型设计的三个误区

1. 不要模型设计
2. mongodb应该用一个超级大文档来组织所有数据
3. mongodb不支持关联或者事务

以上都是误区!~

文档模型其实很多时候关系都放在一个文档中了。其实就是我们直接设计一下json就行。

mongodb分布架构 mongodb 模型_mongodb_05

四、如何考虑MongoDB 文档模式设计的基本策略呢?

  • 性能
    这个模型是否性能不错,能够支撑高并发、低延迟的读写。
  • 开发易用
    MongoDB的模式设计和关系型大不相同,我们说MongoDB是为应用程序设计的,而不是为了存储优化的。如果可以达到最高性能的话,我们甚至可以做一些反范式的东西。

内嵌模式 EMBEDDED DOCUMENTS

1:1 关系建模
内嵌为主,做为子文档形式或直接在顶级
1:N关系建模
同样以内嵌为主,用数组表示一对多。 例如一个人可有多个手机号等,我们用手机号数组。
N:N关系建模
不需要映射表(传统关系数据库的多对多有个映射表),还是通过内嵌数组表示一对多,通过冗余来实现N-N。

总结:内嵌是monodb建模的主要手段!一般建议的是先考虑内嵌, 直接按照你的对象模型来设计你的数据模型。如果你的对象模型数量不多,关系不是很复杂,那么恭喜你,可能直接一种对象对应一个集合就可以了。

一个高效的数据模型能够很好的满足你应用程序的需求。设计一个文档数据结构最关键的考量就是决定是否使用 embed 还是 引用。

引用模式 REFERENCED DOCUMENTS

有一些时候,使用引用则难以避免。比如说, 一个明星的博客可能有几十万或者几百万的回复,这个时候如果把comments放到一个数组里,可能会超出16M的限制。这个时候你可以考虑使用引用的方式,在主表里存储一个id值,指向另一个表中的 id 值。使用引用要注意的就是:从性能上讲,一般我们可能需要两次以上才能把需要的数据取回来。更加重要的是:需要把数据存放到两个集合里,但是目前为止MongoDB并不支持跨表的事务性,所以对于强事务的应用场景要谨慎使用。

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

  • 内嵌文档太大,数 MB 或者超过 16MB (MongoDB 文档大小不能超过16MB)
  • 内嵌文档或数组元素会频繁修改
  • 内嵌数组元素会持续增长并且没有封顶

数据建模设计最佳实践

关于文档设计

  • 字段名不要太长,建议对于大型数据集,使用短字段名将数据存储在集合中,例如fname而不是firstName
    当数据集非常大时,这可能会增加大量内存。
  • 防止太深的数据嵌套。(超过2层操作比较复杂)
  • 不使用中文,标点符号等作为字段名

关于关于查询和索引

  • 每个查询都必须有对应的索引
  • 尽量使用覆盖索引 Covered Indexes(可以避免读数据文件)
  • 使用projection 减少返回到客户端的文档的内容
  • 避免使用count
    尽量不要计算总页数,特别是数据量大和查询条件不能完全命中索引时。
  • 合理使用索引,为了追求索引的速度,索引是加载在内存中使用的,不能合理使用索引后果严重。

关于写入

  • update语句,只包括更新的字段
  • 尽可能使用批量插入提升写入性能
  • 使用TTL索引自动过期日志类型的数据

五、 其他

MongoDB覆盖索引查询

MongoDB索引
参考URL: https://www.kancloud.cn/idzqj/customer/1475258

复合索引(Compound Indexes)指一个索引包含多个字段,用法和单键索引基本一致。

官方的MongoDB的文档中说明,覆盖查询是以下的查询:

  • 所有的查询字段是索引的一部分
  • 所有的查询返回字段在同一个索引中

由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在整个数据文档中检索匹配查询条件和返回使用相同索引的查询结果。

因为索引存在于RAM中,从索引中获取数据比通过扫描文档读取数据要快得多。

为了测试覆盖索引查询,使用以下 users 集合:

{
   "_id": ObjectId("53402597d852426020000002"),
   "contact": "987654321",
   "dob": "01-01-1991",
   "gender": "M",
   "name": "Tom Benzamin",
   "user_name": "tombenzamin"
}

MongoDB使用 ensureIndex() 方法来创建索引
db.COLLECTION_NAME.ensureIndex({KEY:1})语法中 Key 值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。

方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)。

我们在 users 集合中创建联合索引,字段为 gender 和 user_name :

>db.users.ensureIndex({gender:1,user_name:1})

现在,该索引会覆盖以下查询:

>db.users.find({gender:"M"},{user_name:1,_id:0})

也就是说,对于上述查询,MongoDB的不会去数据库文件中查找。相反,它会从索引中提取数据,这是非常快速的数据查询。

由于我们的索引中不包括 _id 字段,_id在查询中会默认返回,我们可以在MongoDB的查询结果集中排除它。

下面的实例没有排除_id,查询就不会被覆盖:

>db.users.find({gender:"M"},{user_name:1})

MongoDB 使用 count 带来的分页问题与应对措施

MongoDB 使用 count 带来的分页问题与应对措施

参考

[推荐]『MongoDB』MongoDB模型设计的成神之路
MongoDB 进阶模式设计
参考URL: https://mongoing.com/mongodb-advanced-pattern-design
MongoDB (三) 数据模型
参考URL: https://www.bilibili.com/read/cv16319819/
MONGODB数据建模设计_MONGODB中的数据建模
参考URL: https://www.freesion.com/article/81661115755/
MongoDB 覆盖索引查询
参考URL: https://cloud.tencent.com/developer/article/1860863
性能最佳实践:MongoDB索引
参考URL: https://baijiahao.baidu.com/s?id=1679205373255697736