性能系列最佳实践-数据建模

MongoDB

这个系列适用于谁?

虽然我们将要介绍的最佳实践并非面面俱到,但在本系列中会有一些建议对您很有用,无论您是:

  • 刚开始您的第一个项目还是经验丰富的MongoDB开发人员。

  • 在使用全托管云数据库MongoDB 服务,或自建MongoDB。

我们在本文中要涵盖什么内容?

我们将从两个关键考虑因素开始,这将为我们在接下来的博客系列中讨论的所有性能最佳实践奠定基础。首先,我们将讨论模式设计以及为您启动的关键资源,然后转向为您的应用程序中最常访问的数据和索引调整RAM大小。这就是我们所称的“工作集”。

数据建模至关重要

性能优化的第一步是了解应用程序的查询模式,从而设计数据模型并相应地选择适当的索引。根据应用程序的查询模式调整数据模型可以生成更高效的查询,增加插入和更新操作的吞吐量,并更有效地在分片集群中分配工作负载。

虽然MongoDB具有灵活的模式,但这并不意味着您可以忽视模式设计!虽然您随时可以修改模式,但在项目初期遵循模式设计的最佳实践将有助于避免未来的潜在重构工作。

JSON文档的一个主要优势是您可以根据应用程序的需要灵活地数据建模。数组和子文档的嵌套使得文档能够很好地表达数据之间的复杂关系。但您还可以将数据建模为平面、表格和列式结构,或者简单的键值对、文本、地理空间和时间序列数据,甚至是连接图数据结构的节点和边缘。最佳的模式设计将由您的应用程序查询模式来确定。

数据建模的关键考虑因素和资源

在设计数据模型时,您需要首先做出的决策之一是如何对数据之间的关系进行建模。决定何时在单个文档内嵌入一个文档,或者在不同集合中的单独文档之间创建引用,是一个应用程序特定的考虑。然而,在模式设计过程中,有一些通用的考虑因素可以指导这个决策。

嵌入

具有1:1关系的数据显然是单个文档内嵌入的明显和自然的选择。具有一对多关系的数据,其中“多”个对象始终与其父文档一起出现或在其上下文中查看,也最适合通过嵌入来处理。因为这些数据总是一起访问,将其一起存储在同一文档中是最优的。

由于数据的本地性,嵌入通常在读取操作方面提供更好的性能,因为可以通过单个内部数据库操作请求和检索相关数据,而不是查找存储在不同集合中的文档。嵌入数据模型还使得在单个原子写操作中更新相关数据成为可能,因为单个文档写入是事务性的。

然而,并不是所有的1:1和一对多关系都适合嵌入到单个文档中。在以下情况下应该在不同集合的文档之间使用引用:

  • 经常读取一个文档,但包含的数据很少被访问。将这些数据嵌入只会增加集合的内存需求(工作集)。

  • 文档的某个部分经常被更新,并且大小不断增长,而文档的其余部分相对静态。

  • 组合文档大小会超过MongoDB的16MB文档限制,例如在建模多对一关系时,如产品评论与产品之间的关系。

引用

引用可以帮助解决上述提到的挑战,并且通常在建模多对多关系时使用。然而,应用程序需要发出后续查询来解析引用,需要额外的往返服务器通信,或者需要使用MongoDB的‘$lookup’聚合管道阶段执行“连接”操作。

深入挖掘

数据建模是一个广泛的主题,并且已经填补了以前的博客系列。为了帮助您做出正确的决策,以下是您应该审查的关键资源摘要:

  • MongoDB文档提供了关于数据建模的广泛部分,从文档数据模型的高级概念开始,然后逐渐进展到实际示例和设计模式,包括有关引用和嵌入的更多详细信息。

  • 您还应该查阅我们的“使用模式构建”博客系列,以了解有关不同用例的特定模式设计最佳实践,包括目录和内容管理、物联网、移动应用、分析和单一视图(即客户360)。它将这些用例与特定的模式设计模式进行叠加,如版本控制、分桶、引用和图形。

  • MongoDB大学提供了一个免费的基于Web的数据建模培训课程。这是一个了解文档数据模型中模式设计的学习的好方法。

审查您的数据模型

一旦您开发了初始数据模型并开始填充样本应用程序数据,有能力对其进行审查将会很有帮助。

MongoDB Compass是MongoDB的免费GUI工具。您可以在Compass上做很多事情,所以在这个博客系列中我们会经常回到这个工具。其中最有用的功能之一是模式可视化,使您能够使用直方图探索您的模式,显示文档字段、数据类型和值。正如您将在系列后面看到的那样,您还可以直接从Compass UI可视化查询解释计划和索引覆盖范围。

图 1:在 MongoDB Compass 中可视化您的架构

在图1中,我们正在审查存储在"restaurants"集合中的文档模式。对于采样的文档,Compass显示字段在每个文档中出现的频率,它们包含的值的范围以及数据类型,以及"categories"数组中的元素数量。Compass文档中详细介绍了如何分析您的模式。

开始使用文档

探索和实验数据建模的最佳方法是在完全托管的阿里云云服务上启动MongoDB。

我们的文档将指导您如何在您选择的地区和云提供商上创建一个免费的MongoDB数据库集群。您还可以加载我们的示例数据集,以便轻松入门文档。

内存大小:确保您的工作集适合内存

除了数据建模之外,性能优化的第二个主要考虑因素是调整您的工作集大小。

与大多数数据库一样,当应用程序的工作集(索引和最常访问的数据)适合内存时,MongoDB的性能最佳。RAM大小是实例大小的最重要因素;如果内存不足,其他优化可能无法显著提高数据库的性能。如果性能与价格/性能之间存在权衡,那么使用快速的SSD来补充较小的RAM量是一种可行的设计选择。您应该测试以找到适合您工作负载和SLA的最佳平衡。

当应用程序的工作集适合内存时,从磁盘读取的活动将会很低。您可以使用我们将在查询分析博客文章中介绍的工具来分析这一点,这是本系列的下一步内容。

如果您的工作集超过所选实例大小或服务器的RAM,请考虑迁移到具有更多内存的实例,或者将数据库分区(分片)到多个服务器上。

无论您是使用云托管MongoDB还是自己管理MongoDB,正确调整工作集大小都是必要的。

  • 如您使用阿里云,请查阅阿里云MongoDB 官方文档,以获取有关计算工作集大小的指导。

  • 在本系列后面,我们将更深入地探讨自建的MongoDB硬件大小调整问题。

阿里云MongoDB 中,扩展计算和存储非常简单。您可以选择进入集群层自动缩放,以响应应用程序需求的变化来调整计算容量。

阿里云MongoDB中,集群层自动缩放会在定义的时间段内监控CPU和内存利用率,并在您配置的限制内调整实例大小。所有缩放事件都是以滚动方式执行的,因此不会对您的应用程序产生影响。撰写本文时,自动缩放是一个测试功能。如果您想要自己控制缩放事件,那么您可以在阿里云MongoDB 控制台中只需点击几下鼠标,或通过API调用来实现。