在MongoDB中使用UUID而不是ObjectID
出于性能原因,我们正在将数据库从MySQL迁移到MongoDB,并考虑MongoDB文档的ID使用什么。我们正在讨论使用ObjectID(这是MongoDB的默认设置)还是使用UUID(这是我们到目前为止在MySQL中一直使用的)。到目前为止,我们支持这些方案的理由如下: 对象: ObjectId是MongoDB的默认值,我假设(尽管我不确定)这是有原因的,这意味着我希望MongoDB能够比UUID更有效地处理它们,或者有另一个更喜欢它们的原因。我还发现,有人提到使用objectid可以提高索引效率,不过最好能有一些指标来衡量这种“更高效”的程度 UUIDs: 我们支持使用UUID的基本论点(这是一个非常重要的论点)是,几乎任何数据库都以某种方式支持UUID。这意味着,如果出于任何原因,我们决定从MongoDB切换到其他应用程序,并且我们已经有了一个API,可以根据文档的ID从DB检索文档,那么这个API的客户端不会发生任何变化,因为ID可以继续保持完全相同。如果我们要使用ObjectID,我真的不确定如何将它们迁移到另一个DB在MongoDB中使用UUID而不是ObjectID,mongodb,Mongodb,出于性能原因,我们正在将数据库从MySQL迁移到MongoDB,并考虑MongoDB文档的ID使用什么。我们正在讨论使用ObjectID(这是MongoDB的默认设置)还是使用UUID(这是我们到目前为止在MySQL中一直使用的)。到目前为止,我们支持这些方案的理由如下: 对象: ObjectId是MongoDB的默认值,我假设(尽管我不确定)这是有原因的,这意味着我希望MongoDB能够比UUID更有效地处理它们,或者有另一个更喜欢它们的原因。我还发现,有人提到使用objectid可以提高索引
是否有人对其中一个选项是否比另一个更好以及为什么更好有任何见解?您是否曾经在MongoDB中使用UUID而不是ObjectID?如果是,您遇到了哪些优点/问题?MongoDB的
\u id
字段可以具有您想要的任何值,只要您能够保证它对于集合是唯一的。当您的数据已经有一个自然键时,没有理由不使用它来代替自动生成的objectid
ObjectID是一个合理的默认解决方案,用于安全生成自己的唯一密钥(并阻止初学者尝试复制SQL的自动增量
,这在分布式数据库中是个坏主意)
由于不使用ObjectID,您还错过了另一个方便的功能:ObjectID在生成时还包括一个unix时间戳,许多驱动程序提供了提取它并将其转换为日期的功能。这有时会使单独的create date
字段冗余
但是当这两种情况对您都不重要时,您可以自由地将UUID用作
\u id
字段。考虑在每种情况下存储的数据量
MongoDB大小为12个字节,打包存储,其各部分按性能进行组织(即首先存储时间戳,这是一种逻辑排序标准)
相反,标准UUID是36字节,包含破折号,通常存储为字符串。此外,即使你删除非数字字符并打算数字存储,你仍然必须满足它的“索引”部分(UUID V1的部分是基于时间戳的)在UUID的中间,并且不适合于排序。现在已经完成了一些允许高性能UUID存储的操作,我甚至还编写了一个帮助管理它的程序
如果您打算使用UUID,请考虑重新组织它以进行最佳索引和排序;否则,您可能会遇到性能问题。
我在前一段时间遇到同样的问题时发现了这些问题。 它们基本上表明,使用Guid而不是ObjectId会导致索引性能下降无论如何,我建议您定制基准,以模仿您特定的现实生活场景,并查看数字的外观,不能100%依赖通用基准。我认为这是一个好主意,Mongo也是如此;它们将UUID列为应用程序的常见选项之一 考虑事项:
- 性能——正如其他答案所提到的,show uuid会导致插入的性能下降。在最坏的情况下(在一个集合中从1000万到2000万个文档),它们的速度大约慢了2-3倍——这是每秒插入2000个(UUID)和7500个(ObjectID)文档之间的差异。这是一个很大的区别,但它的重要性完全取决于您的用例。您是否会一次批量插入数百万个文档?对于我构建的大多数应用程序,常见的情况是插入单个文档。在该测试中,差异要小得多(6250-vs-7500;~20%)。ID类型根本不是限制因素
- 可移植性——其他数据库当然倾向于具有良好的UUID支持,因此可移植性将得到改善。或者,由于UUID更大(更多位),因此可以使用。这种方法不如直接可移植性好,但它确实为您提供了前进的道路
- UUID具有本机支持——您可以在Mongo Shell中使用与使用
ObjectID()完全相同的方法;将字符串转换为等效的BSON对象
- uuid并不特别大——与96位的objectid相比,它们是128位的。(应使用二进制子类型
对其进行编码)0x04
- UUID可以包括时间戳——具体地说,UUIDv1以60位的精度编码时间戳,而ObjectID中为32位。这是超过6个数量级的精度,所以纳米秒而不是秒。它实际上是一种比Mongo/JS日期对象支持的更精确地存储创建时间戳的好方法,但是。。。
- 内置的
函数只生成v4(随机)UUID,因此,要利用这一点,您需要依靠应用程序或Mongo驱动程序来创建IDUUID()
- 与ObjectId不同,因为时间戳不会给您一个自然顺序。这可能是好的,也可能是坏的,这取决于您的用例
- 在ID中包含时间戳通常是个坏主意。你最终泄漏了创建的tim
Method A : Simple int: _id:0, _id:1, ... B : ObjectId _id:ObjectId("5e0e6a804888946fa61a1976"), ... C : Simple string: _id:"A0", _id:"A1", ... D : UUID length string _id:"9575edcc-cb70-4d63-97ed-ee5d624de87b0", ... (but not actually generated by UUID() E : Real generated UUID _id: UUID("35992974-21ea-4f61-b715-2dfaed663b73"), ... (stored UUID() object) F : Real generated UUID _id: "6b16f733-ff24-4172-83f9-e4f96ace6775" (stored as string, e.g. UUID().toString().substr(6,36) Time in milliseconds to perform 100,000 inserts on fresh (empty) collection. Extra M E T H O D (Batch = 100) Payload A B C D E F % drop A to F -------- ---- ---- ---- ---- ---- ---- ------------ None 2379 2386 2418 2492 3472 4267 80% 512 2934 2928 3048 3128 4151 4870 66% 1024 3249 3309 3375 3390 4847 5237 61% 2048 3953 3832 3987 4342 5448 5888 49% 4096 6299 6343 6199 6449 7634 8640 37% 8192 9716 9292 9397 10816 11212 11321 16% Extra M E T H O D (Batch = 1) Payload A B C D E F % drop A to F -------- ----- ----- ----- ----- ----- ----- None 48006 48419 49136 48757 50649 51280 6.8% 1024 50986 50894 49383 49373 51200 51821 1.2%
- 内置的