在MongoDB中使用UUID而不是ObjectID

在MongoDB中使用UUID而不是ObjectID,mongodb,Mongodb,出于性能原因,我们正在将数据库从MySQL迁移到MongoDB,并考虑MongoDB文档的ID使用什么。我们正在讨论使用ObjectID(这是MongoDB的默认设置)还是使用UUID(这是我们到目前为止在MySQL中一直使用的)。到目前为止,我们支持这些方案的理由如下: 对象: ObjectId是MongoDB的默认值,我假设(尽管我不确定)这是有原因的,这意味着我希望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的
\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日期对象支持的更精确地存储创建时间戳的好方法,但是。。。
    • 内置的
      UUID()
      函数只生成v4(随机)UUID,因此,要利用这一点,您需要依靠应用程序或Mongo驱动程序来创建ID
    • 与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%