MongoDB中规范数据模型

    在你开始实现MongoDB数据库时,需要了解所存储的数据的性质,这些数据将如何被存储,以及如何去访问它。理解这些概念可以让你做出提前判断,并构造数据和应用程序以达到最佳性能。

    具体来说,你应该回答以下问题:

  • 应用程序将要使用的基本对象是说明?
  • 不同的对象类型之间的关系是说明:1对1,1对多,还是多对多?
  • 新的对象被添加到数据库中的频度如何?
  • 从数据库中删除对象的频度如何?
  • 对象修改的频度如何?
  • 对象访问的频度如何?
  • 对象该如何进行访问,通过ID,属性值,比较,等等?
  • 对象类型的组将如何进行访问,通过普通的ID,共同属性值,等等?

    一旦你有了这些问题的答案,就可以设计MongoDB数据库中的集合和文档的结构了,以下各节讨论文档,集合和数据库建模的不同方法,你可以在MongoDB中使用它们,以使数据存储和访问最优化。

1,使用文档引用来规范化数据

    数据规范化是组织文档和集合,以减少冗余和依赖的过程。你可以通过确定属性属于子对象的那些对象来规范数据,并且子对象应存放在另一个集合的一个单独的文档中,而不存放在该对象的文档中。通常情况下,你会对具有1对多或多对多的子对象关系的对象来执行这个过程。

    规范化数据的优点在于,数据库大小会变小,因为每个对象的唯一的单个副本将存在于它自己的集合,而不是重复存储在单个集合的多个对象中。此外,如果你经常修改子对象的信息,那么你只需要修改一个实例,而不是在对象的集合中对该子对象的每个记录都进行修改。

    规范化数据的一个主要缺点是,当你要查找需要规范化子对象的用户对象时,必须用一个单独的查询来链接子对象。如果你经常访问用户数据库,则这可能或造成严重的性能问题。

    下面是使用规范化数据的一个例子: 通过添加在对另一个集合的文件的引用来定义规范的MongoDB文档。

User Document
{
	name:"xiaobaicai",
	age:21,
	sex:male,
	favoriteStore:<ObjectId1>
}

FacoriteStore Document
{
	_id:<ObjectId1>,
	name:"my favorite",
	city:"BeiJin"
}

2,使用嵌入式文档反规范化数据

    反规范化数据是对应当被直接嵌入到某个主对象的文档中的该主对象的子对象进行确定的过程。通常情况下,你对大部分是一对一的关系或不会频繁更新的比较小的对象执行这个过程。

    反规范化文档的主要好处是,你可以在一个单独的查询中得到完整的对象,而无须进行额外的查找来与其它集合中的子对象相结合。这是一个重大的性能提高。缺点是,对于有一对多关系的子对象,要在每个文档中都存储它的一个独立的副本,这会减慢插入的速度,还占用额外的磁盘空间。

    以下是一个反规范化的例子:

User Document
{
	name:"xiaobaicai",
	age:21,
	sex:male,
	home:{
		phone:"111111111",
		street:"2222222",
		city:"BeiJin"
	},
	work:{
		phone:"3333333",
		city:"BeiJin"
	},
}

3,使用封顶集合

    MongoDB很大的一个特点就是能够建立一个封顶集合。封顶集合是具有固定大小的集合。当一个新的文档需要被写入到超过该集合的大小的集合时,集合中最旧的文档会被删除,并插入新的文档。对于插入,检索和删除率很高的对象,封顶集合的效果很好。

    以下是使用封顶集合的好处:

  • 它们保证插入顺序被保留。因此查询不需要利用一个索引来按照文档被存储的顺序返回它们,这消除了索引的开销
  • 它们还保证插入顺序与磁盘上的顺序是相同的,这是通过禁止增加文件大小的更新做到的。这消除了重新定位和管理文件的新位置的开销。
  • 它们自动移除集合中最陈旧的文件。因此,你不需要在自己的应用程序代码中实现删除,但你需要小心地使用封顶集合,因为它们均受到了如下限制:
  • 一旦被插入到封顶集合,文档就无法更新到更大的尺寸。虽然可以更新,但是,新数据必须与原数据的大小相同或比原数据的大小更小。
  • 不能从封顶集合中删除文档。这意味着即使数据不被使用,它也在磁盘上占用空间。虽然你可以显示删除封顶集合来有效地删除所有条目,但你需要重新创建它才能再次使用它。

    封顶集合的一个良好用处是作为交易系统中的滚动日志。你可以随时访问日志的最后X个条目。而无须显示地清理最陈旧的条目。

4,了解原子写操作

    写操作是原子的,在MongoDB的文档级别,在同一时间只有一个写操作。这意味着,同时只有一个进程可以更新单个文档或单个集合。因此,对那些反规范的文档的写操作是原子的。然而,对规范化文档的写入需要分别对在其他集合的子对象进行写操作,因此,对规范化对象的写操作作为一个整体可能不是原子的。

    在设计你的文档和集合时,你需要牢记原子写操作,以确保你的设计符合应用的需求。换句话说,如果你绝对必须把一个对象的各个部分作为一个整理以原子的方式写入,就需要用反规范的方式来设计对象。

5,考虑文件增长

    当你更新文档时,你需要考虑新的数据将会对文档的增长有什么样的影响。MongoDB在文档中提供了一些填充,以便容纳更新操作过程中典型的增长。但是如果更新导致文件增大到超过磁盘上已分配的空间,MongoDB就必须把该文件迁移到磁盘上新的位置从而招致对系统性能的损害。此外,频繁迁移文件可能导致磁盘碎片的问题,例如,如果一个文件包含一个数组,并且你添加了足够的元素到该数组,就会导致这个问题。

    减轻文件增长的一种方法是,对那些经常增长的属性使用规范化的对象。例如,不是使用一个数组来存储在Cart(购物车)对象中的物品,你可以为CartItem创建一个集合,并把放入Cart对象中的新物品存储为CartItem集合的新文档,并引用在其中的用户Cart中的物品。

6,识别索引,分片和复制的机会

    MongoDB提供了几种机制来优化性能,可扩展性和可靠性。当你在考虑数据库设计时,应考虑以下每个选项。

  • 索引:索引通过构建可以很容易进行排序的查找索引来改善经常执行的查询的性能。集合的_id属性会自动建立索引,因为通过ID来查找条目是一种常见的做法。但是,在实现索引之前,你还需要考虑用户还会用什么其他方式来访问数据,使得索引也将提高这些查询的性能。
  • 分片:分片是对数据的大集合进行切片的过程,这种大集合可以被划分到集群中的多个MongoDB服务器。每个MongoDB服务器都被认为是一个分片。这提供了利用多台服务器来支持针对一个大系统的大量请求的好处。因此,它提供了对数据库的横向扩展。你应该观察数据的大小和将要访问它的请求的数量,以确定是否对集合分片和分多少片。
  • 复制:复制是对在集群中的多个MongoDB实例上的数据进行拷贝的过程。在考虑数据库的可靠性方面,应事先复制,以确保关键数据的备份副本始终是随时可用的。

7,大集合与大量集合的对比

    在设计MongoDB的文档和集合时,另一件要考虑的重要事情是设计中需要的集合数量。具有大量集合真的是没有重大的性能问题;但具有大量条目的同一个集合,确实会有性能问题。你应该考虑如何把大集合分解为更多的可使用的块。

    比如,你在一个数据库中存储用户过去购买活动的交易历史记录。你知道,对于这些已完成的购买活动,你将永远不会针对多个用户一起查找它们。你只需要使用户能查看他或她自己的历史记录。如果你有成千上万拥有大量交易的用户,那么为每个用户建立一个单独的集合,用来存储用户各自的历史记录,将是有意义的。

8,决定数据生命周期

    数据库设计中最经常被忽视的一个方面是数据的生命周期。文档应该在一个特定的集合中存在多长时间呢?一些集合具有应该无限期地保存的文档,例如,活动的用户账户。但是,请记住,系统中的每个文档都会导致查询集合时性能的损失。你应该在每个集合的文档中定义一个TTL值,即存活时间(time-to-live)的值。

    在MongoDB中有几种实现存活时间机制的方式。其中之一是在应用程序中实现代码来监控和清理旧的数据。另一种方法是利用MongoDB的集合上的TTL设置,它允许你定义一个配置文件,其中规定文档在一定秒数后或在特定时刻被自动删除。对于你只需要最新的文档的集合,另一种方法是实现一个自动保持集合小规模的封顶集合。

9,考虑数据的可用性和性能

    设计MongoDB数据库时,需要考虑的最重要的事情之一是数据的使用,以及它将如何影响性能。在前面的各节描述了不同的方法来解决一些数据大小和优化的复杂性。你应该考虑甚至重新考虑的最后一件事是数据的可用性和性能。最终这些是任何Web解决方案及其背后的存储的两个最重要的方面

    数据的可用性是指一个数据库满足网站的功能的能力。你需要确保数据可用访问,以便网站可以正常运行。用户将不会容忍一个根本没有他们想要的工作的网站。这这里,数据的准确性也很重要。

    然后你可以考虑性能。数据库必须能够以合理的速度传递数据。

    在一些复杂的情况下,你可能会发现有必要评估数据的可用性,然后是性能,之后再回到可用性,经过几个循环,直到你得到正确的平衡。此外,请记住,今天的可用性要求可随时更改。记住这会影响你如何设计文档和集合,使得如果有必要,它们能够在未来变得更具可扩展性。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值