从另一个 table 引用的 table 获取数据的时间复杂度是多少?

What is the time complexity of fetching data from a table that is referenced in another table?

const image_schema = () => {
  const common_fields = {
    user_id: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "user",
      required: true,
    },
    file_name: {
      type: String,
      required: true,
    },
  };
  return new mongoose.Schema(common_fields, {
    collection: `image`,
    timestamps: true,
  });
};

以上是 image 集合的 mongoDB 架构。

每当我需要获取此 table 中的行子集时,我还需要从 user table 中获取相应的 user 信息,即被 user_id 列引用。

user table 中获取附加列的时间复杂度是多少?

如果 user 集合中的这些额外列包含在 image 集合中,从而破坏规范化,速度性能会不会显着提高?

What is the time complexity of fetching the additional columns from the user table?

好吧,对于每张图片,无论您是使用 $lookup 还是在初始获取后的代码中获取它,都需要执行额外的读取操作。

所以这种方法有明显的性能开销(但是在“现实生活”中这种差异通常是可以忽略的),话虽如此,我个人在大多数情况下仍然更喜欢“规范化”方法。

这两种方法之间存在权衡,如果您的用户从未更新过,图像收集的额外存储使用量是一个 none 问题,那么也许您可以从打破“规范化”中获益。这实际上取决于您的产品使用情况。

在实际决定之前需要考虑很多因素,我认为(数据的)规模和实际性能需要成为前 2 个因素

从技术上讲,嵌入式文档的 O(1)query[ 中引用文档的 O(n) =38=] 时间在 mongodb 端,但也有数据 transfer 和 mongoose hydration - 全部两种情况都是 O(n)。本质上它是相同的 O(n),但梯度稍差。请阅读下面的详细信息。

请注意 mongoose(撰写本文时为 v6)不使用 $lookup 但 "more powerful alternative called populate()" 因为它是 mongoose,大部分时间花在客户端将 bson 解组为 json,然后将 json 合成 Mongoose 模型。

Mongoose 批量获取refs,默认5000个文档,所以如果查询不到5000张图片,需要多查询一次才能获取所有被引用的用户。尽管从技术上讲它是 O(n) 绝对值非常小 - 如果用户适合工作集,则查询数据服务器端是毫秒级的问题。您可能会花费更多时间将数据从 mongo 传输到客户端。

将 bson 转换为 json 需要更多时间。它是 O(n),在这种情况下,n 是字段数 x 对象数。这是 mongo nodejs 驱动程序的一部分,您在这里唯一可以改进的是仅投影必填字段。

最昂贵的部分是将 json 转换为 Mongoose。复杂度仍然是 O(n),但它非常耗时,甚至有 lean 选项可以跳过此步骤,return 普通 json 以获得更高的性能。所以使用:

.populate({
  path: 'user_id',
  select: <only required user's info> ,
  options: { lean: true}
})

将使开销可以忽略不计。请记住,用户的字段将是只读的。

数据修改比时间复杂度更重要。虽然非规范化可能会显着提高查询速度,但它会打开一个完整的数据同步蠕虫罐——如果您更改用户 table 中的“相应用户信息”,它不会自动反映在存储在中的用户信息中“图像”集合。

因此,如果您对数据进行非规范化,则需要考虑的事项很少:

  • 您将需要更改用户更新逻辑以更新所有相关集合中的信息
  • 您可能需要将其包装在多文档事务中以确保数据完整性
  • 您将需要从应用程序外部监控更改,例如使用 mongosh
  • 手动更改