首页 > 解决方案 > Mongo 优化:查询性能与数据库结构

问题描述

上下文:连接到 MongoDB 4.0 服务器的 NodeJs (meteorjs) 应用程序

我有一组我经常计算的数据,我需要存储 oevr 时间,然后从我的应用程序访问一组特定的数据。该集合是一个由 12 000 个对象组成的数组,其最终权重约为 3MB(通过对只有一组数据的集合使用 MongoDB 集合统计信息测量:大小:3,3MB;计数:12964)。它与一些计算参数有关。我需要使用查询来检索集合。

我必须在两种数据库结构之间进行选择:

选项 1: 一个集合存储具有 ID 的计算引用(我们将其命名ReferenceCollection),另一个集合每个计算的所有 12000 个对象存储为单个文档,并且 referenceId 指向之前创建的 ID。

这是一个示意图:

ReferenceCollection :
|--- _id: ObjectId("a")
|--- computation : "my reference"

ResultCollection : 
|--- _id: ObjectId("b")
|--- referenceId : ObjectId("a")
|--- fieldResut1 : data
.
.
|--- fieldResut20 : data

要检索该集合,我将使用计算参数查询第一个集合中的 referenceId),然后使用引用 Id 查询第二个集合以获取 12 000 个文档。

let reference = ReferenceCollection.findOne({computation: "my reference"}) // this is lightweight
let results = ResultCollection.find({referenceId: reference._id}) // this search for the 12 000 results

选项 2: 存储计算引用的单个集合,其中包含一个包含数据的数组的键

这是一个示意图:

ResultCollection : 
|--- _id: ObjectId("b")
|--- computation : "my reference"
|--- result : Array(    
    |--- fieldResut1 : data
    .
    .
    |--- fieldResut20 : data
)

要检索该集合,我将只使用我的计算参数进行一次查询,以获取包含我所有数据的单个文档。

问题: 我遇到了第一个选项的性能问题:从 MongoDB 桌面客户端(studio 3T)查询和检索所有 12000 个文档非常慢:在我的设置中需要 3 秒。第二个选项只需 1 秒即可检索(这些时间包括数据的下载)。它导致我的应用程序在获取数据时等待很多。

返回游标时从服务器上的 mongoshell 查询非常快(选项 1 大约 20 毫秒)。


您能否确认选项 2 是存储此数据的好选择?

关于数据结构,我还有其他选择吗?

我在单个节点上运行 MongoDB。您认为设置副本集有助于提高读取性能吗?

标签: databasemongodbperformanceoptimizationdata-structures

解决方案


在这种情况下,您可能会发现差异主要是由于必须执行两个连接/查询,这主要与您的网络相关。

例如,如果在事务集合中引用的用户集合,您将使用选项 1。

这个想法是,如果您需要连接两个集合,则只有在连接集合将被多次引用并且具有复杂文档时才这样做。

如果只是有一个名称集合,然后在另一个集合中引用,那么这是错误的。

如果您需要连接两个 Mongo 集合,请考虑使用聚合,以便 Mongo 服务器可以在 1 次命中中获取数据,而不是需要执行多个查询。

编辑:

为了让您了解性能,现在的第一个选项将花费两倍的时间,纯粹是因为它必须连接两次。如果相同的查询经常发生,那么您真的会看到性能受到无益的影响(除非“计算”字段发生很大变化,那么这可能证明它是合理的)。如果您使用聚合,那么您不会真正看到任何性能损失,因为它被视为单个连接。

选项二只是一次查找,然后是返回数组数据所需的时间。因此,在大多数情况下,使用聚合时与选项 1 相同。

还要考虑如果数组由复杂对象组成,它可能是一个瓶颈。理想情况下,您会避免使用数组并将其展平为带有字段的单个文档。这样,当您进行查询时,您可以设置要返回的字段,从而不返回不需要的字段。


推荐阅读