MongoDB和复合主键

时间:2014-04-19 00:38:35

标签: mongodb composite-primary-key primary-key-design

我正在尝试确定在mongo db中处理复合主键的最佳方法。与该系统中的数据交互的主要密钥由2个uuids组成。 uuids的组合保证是唯一的,但是没有个体uuids。

我看到了几种管理方法:

  1. 使用由2个值组成的主键对象(建议here

  2. 使用标准的自动生成的mongo对象id作为主键,将我的密钥存储在两个单独的字段中,然后在这两个字段上创建复合索引

  3. 使主键成为2 uuids

  4. 的哈希值
  5. 我目前不知道的其他一些很棒的解决方案

  6. 这些方法的性能影响是什么?

    对于选项1,由于具有非连续键,我担心插入性能。我知道这可以扼杀传统的RDBMS系统,我已经看到迹象表明在MongoDB中也是如此。

    对于选项2,拥有一个永远不会被系统使用的主键似乎有点奇怪。此外,似乎查询性能可能不如选项1中的好。在传统的RDBMS中,聚簇索引提供最佳查询结果。 MongoDB中有多相关?

    对于选项3,这将创建一个单个id字段,但再次插入时不会是顺序的。这种方法还有其他优点/缺点吗?

    对于选项4,那么......选项4是什么?

    此外,还有一些讨论可能在将来的某个时候使用CouchDB而不是MongoDB。使用CouchDB建议使用不同的解决方案吗?

    更多信息:可以找到有关此问题的一些背景信息here

4 个答案:

答案 0 :(得分:36)

你应该选择1。

主要原因是你说你担心性能 - 使用始终存在的_id索引并且已经唯一将允许你节省必须维护第二个唯一索引。

  

对于选项1,我担心插入性能会有所影响   非顺序键。我知道这会破坏传统的RDBMS系统   而且我已经看到迹象表明MongoDB也可以这样做。

你的其他选择不能避免这个问题,他们只是将它从_id索引转移到辅助唯一索引 - 但现在你有两个索引,一旦这是正确平衡的,另一个是'随机访问。

只有一个原因可以对选项1提出质疑,即如果您打算只通过一个UUID或其他UUID值来访问文档。只要你总是提供这两个值并且(这部分非常重要)你总是在所有查询中以相同的方式对它们进行排序,那么_id索引将有效地满足它的全部用途。

详细说明为什么必须确保始终以相同的方式排序两个UUID值,在比较子文档{ a:1, b:2 }不等于{ b:2, a:1 }时 - 您可以拥有一个包含两个文档的集合拥有_id的那些值。因此,如果您将_id与字段存储为第一个,那么您必须始终在所有文档和查询中保留该顺序。

另一个警告是_id:1上的索引可用于查询:

db.collection.find({_id:{a:1,b:2}}) 

可用于查询

db.collection.find({"_id.a":1, "_id.b":2})

答案 1 :(得分:6)

我有一个选项4:

使用自动_id字段,为两个uuid而不是单个复合索引添加2个单字段索引。

  1. _id索引将是连续的(虽然在MongoDB中不那么重要),但很容易受到影响,您可以让MongoDB进行管理。
  2. 使用2个uuid索引可以进行任何类型的查询(第一个,第二个或任何顺序),它们占用的空间少于1个复合索引。
  3. 如果你在同一个查询MongoDB中同时使用两个索引(以及其他索引)intersect them(v2.6中的新内容),就像使用复合索引一样。

答案 2 :(得分:4)

我会选择2选项,这就是为什么

  1. 如第1段所述,拥有两个单独的字段而不是两个连接的字段,将使您可以灵活地创建其他索引组合以支持将来的查询请求,或者如果结果是,则一个键的基数更高然后另一个。
  2. 拥有非连续键可以帮助您在分片环境中插入时避免热点,所以它不是一个糟糕的选择。对于我来说,分片是最好的方法,可以扩展集合上的插入和更新,因为写锁定在数据库级别(2.6之前)或集合级别(2.6版本)

答案 3 :(得分:2)

我会使用选项2.您仍然可以创建一个处理UUID字段的索引,并且性能应该与复合主键相同,除非它更容易工作用。

另外,根据我的经验,即使没有严格要求,我也从不后悔提供一些独特的ID。也许这不是一个不受欢迎的意见。