MongoDB--数据的组织形式和优化数据

本文探讨MongoDB的数据组织形式,包括范式化与反范式化的优缺点,以及如何优化数据操作,如文档增长和旧数据删除。同时,讨论了数据库和集合设计原则,以及一致性锁的工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MongoDB–数据的组织形式和优化数据

一:范式化和反范式化

范式化:将数据分散到多个不同的集合,不同集合之间可以相互引用数据。如果要修改数据,只需修改保存这块数据的文档就行。但是MongoDB没有连接(join)工具,所以在不同集合之间执行连接查询需要进行多次查询。

反范式化:将每个文档所需的数据都嵌入在文档内部。每个文档都有自己的数据副本,而不是所有文档共同引用一个数据副本。但是如果数据发生变化,那么所有相关文档都需要进行更新。

范式化能够提高数据写入速度,反范式化能够提高数据读取速度。

一般来说有四种数据组织方式:

1.学生表,课程表,学生和课程之间的关系表;由于MongoDB不能join,所以如果要查,学生选修的课程,就需要三次查询;(范式化)

2.学生表(有一个字段包含了课程表的引用),课程表;只需要两次查询(半反范式化)

3.学生表中内嵌课程表,只需要一次查询,但是会占用更多的存储空间,而且数据同步困难(完全反范式化)

4.学生表中不仅内嵌课程表还还要课程表的引用,这样内嵌的文档可以随着需求修改

适合引用适合内嵌
子文档较大子文档较小
数据经常改变数据不会定期改变
中间阶段数据必须一致最终数据一致
快速写入快速读取

二:优化数据操作

定位到读写瓶颈。针对性优化,例如合理使用索引,优化写操作尽量减少使用索引,优化读操作要正确使用索引和将所需信息放在单个文档。

1. 优化文档增长

更新数据的时候明确数据增长的程度,是否会导致文件体积变大。可为文档预留足够的增长空间,避免文档移动。

例如有一个文档中有一个字段names,是一个数组,会增长数据,我们可以手动为文档留出足够的空间,在names字段后面再加一个fill字段,可以在第一次插入文档或者upsert时使用$setOnInsert创建这个字段

db.mong.update({},{$setOnInsert:{"fill":"...................................."}},{true},{true})

在更新文档字段names的时候,使用"$unset"移除fill字段,这样names就有了空白空间用于增长

db.mong.update({"_id":1},{"$push":{"names":{"$each":["zs","li","we"]}},"$unset":{"fill":1}})
2. 删除旧数据

最常见的就是使用TTL索引和固定集合

三:数据库和集合的设计

  • 相近的文档应该放在相同的集合中;
  • 由于MongoDB不允许跨集合聚合数据,所以需要聚合的数据要放在相同集合中;
  • 可以让不同的数据库位于不同的磁盘分卷中,经常访问的可以放在SSD中;
  • 无法将数据从一个数据库转移到另一个数据库中

四:一致性锁

当进行读操作的时候会加读锁,这个时候其他读操作可以也获得读锁。但是不能或者写锁。

当进行写操作的时候会加写锁,这个时候不能进行其他的读操作和写操作。
在3.0之后的版本,WiredTiger提供了文档(不是集合)级别的锁

MongoDB内部处理请求的机制:服务器为每一个数据库连接维护一个请求队列,客户端每次发来的请求都会添加到请求队列的末尾。每个请求队列对应的是一个连接,如果有多个连接同时读和写就会存在了一致性的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值