32

MongoDB 使用 ObjectId 类型作为 _id。

如果我将 _id 设为递增整数会不会很糟糕?

(有这个宝石,如果你有兴趣)

4

3 回答 3

37

不,它一点也不差,事实上内置在ObjectId索引中相当大,所以如果你相信你有更好的东西,那么你非常欢迎将_id字段的默认值更改为任何值。

但是,这是一个很大的问题,在决定远离默认公式时,有一些考虑因素ObjectId,特别是在使用自动递增 _ids 时,如下所示:https ://docs.mongodb.com/v3.0/tutorial/创建自动递增字段

多线程并不是一个大问题,因为findAndModify原子锁实际上可以解决这个问题,但是你只是遇到了第一个问题。findAndModify不是最快的功能,也不是最轻的功能,经常使用它时性能明显下降。

无论如何,您还必须考虑自己执行此操作的开销,即使没有findAndModify. 对于每个插入,您都需要一个额外的查询。想象一下,有一个唯一的 id,您必须在每次要插入时查询其唯一性。最终,您的插入率将下降到爬行,并且您的锁定时间将增加。

当然,ObjectId它真的很擅长保持唯一性,而不必在插入之前通过触摸数据库来检查或制定自己的唯一性,因此它没有这种开销。

如果您仍然觉得整数 _id 适合您的场景,那么就去做吧,但请记住上面描述的开销。

于 2012-12-27T16:52:49.060 回答
16

你可以这样做,但你有责任确保整数是唯一的。

MongoDB 不像大多数 SQL 数据库那样支持自增字段。当您的分布式或多线程应用程序具有多个创建新数据库条目的进程和/或线程时,您必须确保它们使用相同的计数器。否则可能会发生两个线程尝试在数据库中存储具有相同 _id 的文档。

当这种情况发生时,其中一个将失败。这意味着您必须等待数据库返回成功或错误(通过调用 GetLastError 或通过将写入问题设置为确认),这比仅以即发即弃的方式发送数据需要更长的时间。

于 2012-12-27T13:36:02.947 回答
1

我有一个用例:将 _id 替换为 64 位整数,该整数表示用于搜索的文档索引的 simhash。

由于我打算“获取或创建”,因此提供初始 simhash,并在不存在的情况下创建新记录是完美的。此外,对于任何在谷歌上搜索的人,MongoDB 支持向我解释说,simhashes 绝对适合分片和缩放,甚至比更通用的 ObjectId 更好,因为它们将完美地和内在地跨分片划分数据,并且您可以获得存储的密钥负空间(uint64 比 objectId 小得多,无论如何都需要存储)。

此外,对于您的 Google 员工来说,用 objectId 以外的其他东西替换 MongoDB _id 绝对简单:只需创建一个定义了 _id 的对象;如果您愿意,请使用整数。就是这样:Mongo 将简单地使用它。如果您尝试创建具有相同 _id 的文档,您将收到错误消息(E11000/重复键)。所以像我一样,如果你使用 simhashing,这在所有方面都是理想的。

于 2020-02-26T02:41:34.933 回答