【问题标题】:MongoDB auto increment IDMongoDB 自动增量 ID
【发布时间】:2014-01-19 15:25:35
【问题描述】:

MongodDB中自动生成的ID大小为12 Bytes,大整数的大小为8 bytes。我在 4 台运行 Ubuntu Server 的机器上有一个 mongodb 集群,但我现在只是在测试。插入只能通过一台 nodejs 服务器来完成,但更新和删除可以使用运行在世界各地的本地 c 应用程序的各种机器和 nodejs 服务器来完成。

既然我可以完全控制插入,那么使用自动增量 ID 不是更好吗?

  • 在 1MB 内存中,您可以保存 12 个字节 id 中的 87381 个和 8 个字节中的 131027 个 字节 ID。
  • 使用自动增量 ID 是否值得,是否有好处 除了节省内存?
  • 在性能方面不会比较 8 字节 id 比 12 快 byte id,如果我做索引它不会减小大小吗?

我是怎么做到的:

我有这份文件

{id:0 latestId:174845423}

我很少将其递增 1,我的大多数插入都是批量插入,因此 nodejs 服务器修改要插入的文档循环给每个文档一个递增的 id,在插入操作结束时我添加我更新具有最后一个 id 值的最新 id。

【问题讨论】:

  • 您多久生成一次新 ID?意识到 MongoDB 中没有“自动递增字段”类型,因此您需要使用以下模式:docs.mongodb.org/manual/tutorial/…
  • @WiredPrairie 98% 的日常操作都是读取和更新,因为我说过插入只发生在单个 nodejs 服务器上,所以我可以制作一个具有 id 字段的文档,并在插入操作已完成,它们通常是批量插入,因此我可以将 id 添加到要插入的文档中,并在插入结束时,将 id 文档增加插入的文档数,因此插入操作是精心安排的,并且我完全控制它们
  • 如果你能保证 Id 是唯一的,并且节点进程永远不会重复一个 Id,你可以使用它。但是,如果节点进程突然死亡......除非您将最后一个值保存在节点进程之外的某个位置,否则您将如何重新开始 ID 生成?
  • @WiredPrairie 我用我当前的方法更新了这个问题,感谢您指向 nodejs 服务器的死部分,但除此之外我还有什么好处吗?
  • 这感觉像是过早的优化。内存差异并不显着,比较时间差异是不可测量的(8-12 字节?),并且索引肯定会稍微小一些......但它是否值得真的取决于你。如果您对自己的解决方案感到满意并了解潜在问题,我不建议您改用其他方法。

标签: mongodb


【解决方案1】:

在使用分布式系统时,“自动增量”始终是一个问题,因为它会产生瓶颈:每个新增量都需要读取以前的数据......就像其他一些并行请求一样。

一般来说,“自动增量”会限制并行性,特别是在分布式系统上。

【讨论】:

  • 在我插入文档之前,我将在 nodejs 服务器上进行增量,nodejs 服务器确实跟踪了最新的 id,所以我不会依赖数据库来获取最新的 id 值,所以这样我就可以避免读取以前的数据,在这种情况下,这个配置会不会比自动生成的 id 更好?
  • 听起来您只是将瓶颈从数据库转移到 nodejs 服务器。也许,您应该问自己这个瓶颈是否会限制您。如果不是,那么不要想太多,尽你所能继续你的计划。
【解决方案2】:

当业务用例需要为文档增加数值时,我们使用另一种方法。

在数据库中,我们使用索引创建一个集合:

db.createCollection('sequences');

稍后,我们需要一个集合的递增值,我们创建一个序列:

db.sequences.insertOne ( {_id: 'orderId' , value : 0 } );

然后,当我们需要下一个值时,我们使用:

async function getNextValue(seqName) {
    const sequence = await db.sequences.findOneAndUpdate(
        { _id: seqName },
        { $inc: { value: 1 } },
        { returnDocument: 'after' }
    );
    return sequence.value.value;
}

因此,在创建文档时,1) 我们从 DB 中检索下一个序列,2) 添加到模型中,以及 3) 像往常一样插入文档模型。

好处:

  • 线程/进程/服务器安全:一旦检索到下一个值,它将在文档中是唯一的。
  • 序列与集合保存在同一个数据库中:来自任何平台的任何代码或脚本都可以插入文档。

注意事项:

  • 性能。取决于您正在执行的操作,但通常额外往返数据库一次以获取序列不会造成太大伤害。

【讨论】:

    【解决方案3】:

    如果您没有分布式系统,那么您可以使用 node js 的文件系统 (fs) 模块并跟踪那里的所有记录。然后您可以将该值保存在 mongo dB 中。

    附: - 如果您没有分布式系统,这可以工作。

    或者
    您可以为传入的数据条目创建一个记录队列,然后以 dB 为单位保存。

    【讨论】:

      猜你喜欢
      • 2019-06-06
      • 2020-07-19
      • 2017-04-20
      • 2018-04-11
      • 1970-01-01
      • 2018-12-06
      • 2016-10-31
      • 2015-04-27
      • 2011-01-01
      相关资源
      最近更新 更多