MongoDB自增ID

7
自动生成的MongoDB ID大小为12个字节,大整数的大小为8个字节。我在4台运行Ubuntu Server的机器上拥有一个MongoDB集群,但目前只是在测试。插入只能通过一个Node.js服务器完成,但更新和删除可以使用世界各地运行本机C应用程序的多台机器和Node.js服务器完成。
既然我对插入具有完全控制权,那么使用自增ID是否更好呢?
  • 在1MB内存中,您可以保存87381个12字节ID和131027个8字节ID。
  • 除了节省内存之外,是否值得使用自增ID,是否有其他好处?
  • 就性能而言,比较8字节ID是否比12字节ID更快,并且如果我创建索引,则是否会减小大小?
我的做法如下:
我有这个文件
{id:0 latestId:174845423}

我很少将其增加1,大多数情况下我进行的是批量插入,因此nodejs服务器会在循环中修改要插入的文档,并为每个文档分配递增的ID。在插入操作结束时,我会更新最新的ID值。


2
你会多久生成一个新的ID?请注意,在MongoDB中没有“自增字段”类型,因此您需要使用诸如http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/之类的模式。 - WiredPrairie
@WiredPrairie 我日常操作中有98%是读取和更新,正如我所说的,插入只发生在单个nodejs服务器上,因此我可以创建一个具有id字段的文档,并在完成插入操作时将其添加到其中。它们通常是批量插入,因此我可以将id添加到要插入的文档中,并在插入结束时按插入的文档数量递增id文档,这样插入操作就被编排了,我对它们拥有完全控制。 - Kanka
1
如果您能保证ID是唯一的,并且节点进程永远不会重复使用ID,那么您可以使用它。但是,如果节点进程突然死亡...除非您在节点进程之外的某个地方保存了最后一个值,否则您将如何重新启动ID生成? - WiredPrairie
也许不值得为它带来的复杂性而麻烦。 - yǝsʞǝla
2
这感觉像是过早的优化。内存差异不明显,比较时间差异不可测(8-12个字节?),而且索引可能会稍微小一些...但是否值得取决于你自己。如果您对解决方案感到满意并了解潜在问题,我不建议您切换到其他东西。 - WiredPrairie
显示剩余2条评论
3个回答

12

在处理分布式系统时,“自增”始终是一个问题,因为它会创建一个瓶颈:每个新的自增都需要读取先前的数据,就像其他并行请求一样。

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


在插入文档之前,我将在Node.js服务器上执行增量操作。Node.js服务器确实跟踪最新的ID,因此我不会依赖数据库来获取最新的ID值,这样我就可以避免读取先前的数据。在这种情况下,使用此配置是否比自动生成的ID更好? - Kanka
1
听起来你只是把瓶颈从数据库转移到了Node.js服务器上。也许,你应该问问自己这个瓶颈是否会限制你。如果不会,那么不要想太多,继续以任何方式编写你的程序。 - Vincent Cantin

6

当业务需求要求文档具有递增的数字值时,我们使用另一种方法。

在数据库中,我们创建了一个带有索引的集合:

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)我们从数据库中检索下一个序列,2)添加到模型中,3)像往常一样插入文档模型。

好处:

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

注意事项:

  • 性能。根据您所做的操作而定,但通常额外进行一次数据库往返以获取序列不会太影响性能。

-1

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

P.S. - 如果您没有分布式系统,这可以起作用。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接