不,一点也不坏。事实上,内置的
ObjectId
在索引中相当大。因此,如果您相信自己有更好的东西,我们非常欢迎您将 _id
字段的默认值更改为任何值。
但是,这是一个很大的但是,在决定放弃默认制定的
ObjectId
时,需要考虑一些因素,特别是在使用自动递增_ids时,如下所示:https://docs.mongodb.com /v3.0/tutorial/创建自动递增字段
多线程并不是一个大问题,因为
findAndModify
和原子锁实际上可以解决这个问题,但随后你就遇到了第一个问题。 findAndModify
不是最快的功能,也不是最轻的功能,经常使用时会发现性能明显下降。
即使没有
findAndModify
,你也必须考虑自己执行此操作的开销。对于每个插入,您都需要一个额外的查询。想象一下,有一个唯一的 id,每次要插入时都必须查询其唯一性。最终你的插入率会下降到极点,你的锁定时间也会增加。
当然,
ObjectId
非常擅长保持唯一性,而无需在插入之前通过接触数据库来检查或制定其自己的唯一性,因此它没有这种开销。
如果您仍然认为整数 _id 适合您的场景,那么就使用它,但请记住上述开销。
你可以这样做,但你有责任确保整数是唯一的。
MongoDB 不像大多数 SQL 数据库那样支持自动增量字段。当您的分布式或多线程应用程序具有多个进程和/或线程来创建新的数据库条目时,您必须确保它们使用相同的计数器。否则,可能会发生两个线程尝试在数据库中存储具有相同 _id 的文档。
当这种情况发生时,其中一个就会失败。这意味着您必须等待数据库返回成功或错误(通过调用 GetLastError 或将写入关注点设置为 acknowledged),这比仅以“即发即忘”的方式发送数据需要更长的时间。
我有一个这样的用例:用 64 位整数替换 _id,该整数表示用于搜索的文档索引的 simhash。
由于我打算“获取或创建”,因此提供初始 simhash,如果不存在则创建一条新记录是完美的。另外,对于任何谷歌搜索的人来说,MongoDB 支持向我解释说 simhashes 绝对适合分片和扩展,甚至比更通用的 ObjectId 更好,因为它们会完美地、内在地跨分片划分数据,并且您可以获取存储的密钥负空间(uint64 比 objectId 小得多,无论如何都需要存储)。
此外,对于 Google 员工来说,用 objectId 以外的其他内容替换 MongoDB _id 绝对简单:只需创建一个定义了 _id 的对象即可;如果您愿意,可以使用整数。就是这样:Mongo 将简单地使用它。如果您尝试创建具有相同 _id 的文档,您将收到错误(E11000/重复密钥)。所以像我一样,如果您使用 simhashing,那么这在各方面都是理想的。