MongoDB模式设计注意事项

模式设计,即在文档中表示数据的方式,对于数据表示来说是非常关键的。最好的方式是按照应用程序希望看到的形式来表示数据。因此,与关系数据库不同,在为模式进行建模之前,首先需要了解查询和数据访问的方式。

模式设计注意事项

以下是在设计模式时需要考虑的几个关键方面。

限制条件

有一些数据库或硬件的限制是你需要了解的。你还需要考虑 MongoDB 的一些特殊之处,比如最大文档大小为 16MB、从磁盘读写完整文档、更新会重写整个文档,以及在文档级别进行原子更新。

查询和写入的访问模式

你需要确定并量化应用程序和更大系统的工作负载。工作负载包括应用程序中的读操作和写操作。一旦知道了查询的运行时间和频率,就可以识别最常见的查询。这些查询是在进行模式设计时需要支持的。一旦确定了这些查询,就应该尽量减少查询的数量,并在设计中确保一起查询的数据存储在同一个文档中。

这些查询中未使用的数据应该存放在不同的集合中。不经常使用的数据也应该移动到不同的集合中。需要考虑是否可以将动态(读/写)数据和静态(主要是读)数据分离开。在进行模式设计时,提高最常见查询的优先级会获得最佳的性能。

关系类型

应该根据应用程序的需要以及文档之间的关系来考虑哪些数据是相关的。然后你就可以确定对于数据或文档,是应该嵌入还是引用。需要弄清楚如何在不执行其他查询的情况下引用文档,以及当关系发生变化时需要更新多少文档。还必须考虑数据结构是否易于查询,比如使用内嵌数组(数组中的数组)对某些关系进行建模。

基数

当确定文档和数据的关联方式后,应考虑这些关系的基数,比如具体是一对一、一对多、多对多、一对百万,还是多对几十亿?确定关系的基数非常重要,可以确保在 MongoDB 的模式中使用最佳格式进行建模。还应该考虑是否会对上百万这一端的对象进行访问还是只访问上层对象的内容,以及相关数据字段的更新与读取的比例。充分考虑这些问题将有助于确定应采用内嵌文档还是引用文档,以及是否应该跨文档对数据进行反范式化处理。

设计模式

模式设计在 MongoDB 中很重要,它能直接影响应用程序的性能。在模式设计中可以使用已知的模式或者采用“搭积木”的方式来解决许多常见的问题。最好一起使用一个或多个模式。

可以使用的设计模式包括以下几种。

多态模式

这种模式适用于集合中的所有文档具有类似但不完全相同结构的情况。它涉及识别跨文档的公共字段,而这些文档需要支持应用程序的公共查询。跟踪文档或子文档中的特定字段将有助于识别数据与不同代码路径或类/子类之间的差异,我们可以在应用程序中编码以管理二者的差异。这允许在文档不完全相同的单个集合中使用简单查询来提高查询性能。

属性模式

这种模式非常适合于文档中部分字段具有希望对其进行排序或查询的公共特性,或者需要排序的字段仅存在于部分文档中,或者这两个条件都满足。它包括将数据重塑为键–值对数组,并在该数组中的元素上创建索引。限定符可以作为附加字段添加到这些键–值对中。此模式有助于查询那些存在许多相似字段的文档,因此需要的索引更少,查询也更容易编写。

分桶模式

这种模式适用于时间序列数据,其中数据在一段时间内被捕获为数据流。在MongoDB 中,将这些数据“分桶”存储到一组文档中,每个文档会保存特定时间范围内的数据,这比在每个时间点/数据点创建一个文档更高效。例如,可以使用一小时的存储桶,并将该时间内的所有数据都放到文档的一个数组中。文档本身有开始和结束时间,以表明这个“桶”涵盖的时间段。

异常值模式

这种模式用以解决少数文档的查询超出应用程序正常模式的情况。这是一种高级设计模式,当流行程度作为一个因素时尤其适用。这一点可以在有影响力的社交网络、图书销售、电影评论等地方看到。它使用一个标志来表示文档是异常值,并将额外的溢出存储到一个或多个文档中,这些文档通过 “_id” 引用第一个文档。应用程序代码将使用该标志进行额外查询,以检索溢出的文档。

计算模式

这种模式可以在需要频繁计算数据时使用,也可以在读取密集型的数据访问模式下使用。此模式建议在后台执行计算,并定期更新主文档。这提供了计算字段或文档的有效近似值,而不必为单个查询连续生成这些字段或文档。这样可以通过避免重复相同的计算来显著减少 CPU 的压力,特别是在读操作会触发计算并且读写比较高的情况下。

子集模式

当工作集超过了机器的可用 RAM 时可以使用这种模式。这种情况可能是大文档造成的,这些文档包含大量的应用程序没有使用的信息。此模式建议将经常使用的数据和不经常使用的数据分割为两个单独的集合。一个典型的例子可能是电子商务应用程序中将一个产品的 10 条最近的评论保存在“主”(经常访问的)集合中,并将所有旧的评论移动到第二个集合中,只有在应用程序需要多于 10 条评论时才进行查询。

扩展引用模式

这种模式用于有许多不同的逻辑实体或“事物”,并且每个逻辑实体或“事物”都有各自的集合,但是你希望将这些实体组织在一起以实现特定的功能。在一个典型的电子商务模式中,订单、客户和库存可能会有单独的集合。当需要从这些单独的集合中收集单个订单的所有信息时,可能会对性能产生负面影响。解决方案是识别出经常访问的字段,并在订单文档中复制这些字段。对于电子商务订单,这样的字段可能是接收商品的客户姓名和地址。这种模式以数据冗余为代价,以减少将信息整合在一起所需的查询数量。

近似值模式

这种模式在需要昂贵资源(时间、内存、CPU 周期)的计算却不需要绝对精确的情况下非常有用。这方面的一个例子是一张图片或一则帖子的“点赞”计数器或一个页面浏览的计数器,其中知道确切的计数(例如,是 999 535 还是 10 000000)是没必要的。在这种情况下,应用此模式可以极大地减少写入次数,例如,仅在每浏览 100 次或更多次时更新计数器,而不是在每次浏览之后都进行更新。

树形模式

当你有很多查询并且数据主要是层次结构时,可以使用这种模式。它遵循前面提到过的,将经常一起查询的数据存储在一起的概念。在 MongoDB 中,可以很容易地将层次结构存储在同一个文档的数组中。在电子商务网站的例子,特别是其产品目录中,通常会有属于多个类别的产品或者这个产品的类别从属于其他某个类别。一个例子就是“硬盘驱动器”,它本身是一个类别,但还属于“存储”类别,“存储”本身又属于“计算机部件”类别,而这还是“电子”类别的一部分。在这种情况下,我们会有一个字段跟踪整个层次结构,另一个字段保存直接类别(“硬盘驱动器”)。保存在数组中的整个层次结构字段提供了对这些值使用多键索引的能力。这可以确保很容易地找到层次结构中与类别相关的所有项目。直接类别字段允许找到与此类别直接相关的所有项目。

预分配模式

这主要用于 MMAP 存储引擎,但仍然有一些可以使用此模式的场景。该模式建议创建一个初始的空结构,稍后对该结构进行填充。例如,一个按天管理资源的预订系统可以跟踪该资源是空闲的还是已预订/不可用的。资源(x)和天数(y)的二维结构使得检查是否可用以及执行计算变得非常简单。

文档版本控制模式

这种模式提供了一种机制来保留文档的旧版本。它需要在每个文档中添加一个额外的字段来跟踪“主”集合中的文档版本,还需要一个额外的集合来保存文档的所有修订版本。此模式具备以下假设:具体来说,每个文档都有有限数量的修订版本,不存在大量需要版本控制的文档,并且查询主要是对每个文档的当前版本进行的。假如这些假设不成立,那么可能需要修改模式或考虑使用不同的设计模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆天至尊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值