用于创建可扩展的MongoDB短ID的策略

时间:2013-01-05 08:54:36

标签: mongodb

我想要比MongoDB的ObjectID更友好地面对ids(即Youtube样式:/ posts / cxB6Ey6)。

我认为为了扩展性,最好将_id保留为ObjectID,所以我想到了两个解决方案:

1)为每个文档添加一个索引的postid字段

2)在_id和postid之间创建一个映射集合

在这两种情况下使用https://github.com/dylang/shortid之类的东西来生成短ID,并且在生成时通过查询数据库确保id是唯一的。 (这个query-generate-insert可以是原子操作吗?)

这些解决方案会对性能产生显着影响吗?

这样做的最佳策略是什么?

3 个答案:

答案 0 :(得分:5)

执行此操作的常规方法是base64编码唯一的id,但是:

  

为每个文档添加索引的postid字段

你肯定想要采用这种方法。在这两个中,我会说这种方法很容易具有最大的可扩展性和性能,因为它只需要一次往返就能得到一个简短的URL细节,而第二个选项将需要2.另一个考虑因素是索引开销不足保持额外的收藏,这有点不费吹灰之力。

我不会替换文档中的_id字段,因为默认的ObjectId在可预见的将来仍然有用。

因此,这会将其限制为URL的短代码的单独字段和索引(唯一键)。

接下来就是你不想要一个强制你在每次插入之前查询数据库唯一性的ID。这是ObjectId闪耀的地方。 ObjectId擅长在客户端应用程序中进行,而在数据库中是唯一的,而无需专门查询这些假设。

首先不需要查询数据库的唯一ID通常是基于时间的。在PHP(http://php.net/manual/en/function.uniqid.php)和MongoDB驱动程序(http://docs.mongodb.org/manual/core/object-id/)中,甚至是你在github(https://github.com/dylang/shortid/blob/master/lib/shortid.js#L50)上链接的插件,它们都使用时间作为唯一的基础。 / p>

考虑到您链接的插件不会查询数据库以检查其自己的ID唯一性我会说这个插件可能非常高效,如果您使用第一个解决方案,那么您应该获得一个很好的基准测试出来的。

答案 1 :(得分:3)

如果您想使用自定义用户友好的短ID替换内置ObjectID,请执行此操作。您可以使用内置_id字段,也可以为自定义ID添加新的唯一索引字段id。使用内置ObjectID的好处是,即使您的数据库非常大,它们也不会重复。因此,通过用短ID替换它们,您可能会冒着id重复的风险。

现在关于表现。我认为最好的解决方案不是查询DB的id,因为通过适当调整的id长度,重复的可能性非常小。因此,在此模型中处理ID重复的最佳方法是检查Mongo响应。如果它以“重复键错误”响应,那么您将生成一个新的。

现在关于缩放。要缩放自定义ID,您只需添加一些符号即可。 “重复键错误”应该是进行更改的触发器。通常不会有这样的错误。所以,如果它们开始出现,那就是缩放的时间。

答案 2 :(得分:1)

我认为为ObjectId字段生成_id不会直接影响可伸缩性或性能。哪有可能发生?

主要区别在于ObjectIds是由MongoDB创建的,您不必为此负责。否则,您必须自己确定id的最佳大小,并确保存储在集合中的每个_id文档字段的唯一值。这是必需的,因为_id用作主键。如果您没有非常大的集合并且需要标识符的自定义值,那么这是合理的。

但是_id字段存在这样的额外好处,它将ObjectId值存储为从时间创建对象ID的机会,并在查询中使用此事实。您还可以使用getTimestamp()方法获取ObjectId创建的时间戳。在这种情况下,对_id进行排序相当于按创建时间排序。

但是如果您要在URL或HTML中使用ObjectId,那么出于安全考虑,您可以加密它。防止信息泄漏和访问对象的创建时间。这可能是安全风险。

关于您的解决方案:

1)我认为这是非常方便灵活的解决方案。在这种情况下,您可以在postId中指定任何不直接依赖于_id的值。

但是这个解决方案的一个小缺点是你必须有额外的字段并创建额外的索引。虽然_id会自动编入索引。

2)从性能和noSQL方法理念的角度来看,我认为这不是一个好的解决方案。