我正在尝试确定在mongo db中处理复合主键的最佳方法。与该系统中的数据交互的主要密钥由2个uuids组成。 uuids的组合保证是唯一的,但是没有个体uuids。
我看到了几种管理方法:
使用由2个值组成的主键对象(建议here)
使用标准的自动生成的mongo对象id作为主键,将我的密钥存储在两个单独的字段中,然后在这两个字段上创建复合索引
使主键成为2 uuids
我目前不知道的其他一些很棒的解决方案
这些方法的性能影响是什么?
对于选项1,由于具有非连续键,我担心插入性能。我知道这可以扼杀传统的RDBMS系统,我已经看到迹象表明在MongoDB中也是如此。
对于选项2,拥有一个永远不会被系统使用的主键似乎有点奇怪。此外,似乎查询性能可能不如选项1中的好。在传统的RDBMS中,聚簇索引提供最佳查询结果。 MongoDB中有多相关?
对于选项3,这将创建一个单个id字段,但再次插入时不会是顺序的。这种方法还有其他优点/缺点吗?
对于选项4,那么......选项4是什么?
此外,还有一些讨论可能在将来的某个时候使用CouchDB而不是MongoDB。使用CouchDB建议使用不同的解决方案吗?
更多信息:可以找到有关此问题的一些背景信息here
答案 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个单字段索引。
_id
索引将是连续的(虽然在MongoDB
中不那么重要),但很容易受到影响,您可以让MongoDB
进行管理。MongoDB
中同时使用两个索引(以及其他索引)intersect them(v2.6中的新内容),就像使用复合索引一样。答案 2 :(得分:4)
我会选择2选项,这就是为什么
答案 3 :(得分:2)
我会使用选项2.您仍然可以创建一个处理UUID字段的索引,并且性能应该与复合主键相同,除非它更容易工作用。
另外,根据我的经验,即使没有严格要求,我也从不后悔提供一些独特的ID。也许这不是一个不受欢迎的意见。