自定义 MongoDB 对象 _id 与复合索引
Posted
技术标签:
【中文标题】自定义 MongoDB 对象 _id 与复合索引【英文标题】:Custom MongoDB Object _id vs Compound index 【发布时间】:2016-12-15 07:42:39 【问题描述】:所以我需要在 MongoDB 中创建一个查找集合来验证唯一性。要求是检查是否重复了相同的 2 个值。在 SQL 中,我会这样做
SELECT count(id) WHERE key1 = 'value1' AND key2 = 'value2'
如果上述查询返回一个计数,则表示该组合不是唯一的。我有两种解决方案,但我不确定哪一种更具可扩展性。我需要针对 30M+ 文档创建此映射。
解决方案 1:
我在 key1 和 key2 上创建了一个带有复合索引的文档集合
_id: <MongoID>,
key1: <value1>,
key2: <value2>
解决方案 2:
我编写应用程序逻辑,通过连接 value1 和 value2 来创建自定义 _id
_id: <value1>_<value2>
我个人觉得第二个更优化,因为它只有一个索引,而且 doc 的大小也更小。但我不确定创建自己的 _id 索引是否是一个好习惯,因为它们可能不是完全随机的。你怎么看?
提前致谢。
更新:
我的数据库已经有很多占用内存的索引,所以我想将索引大小保持在尽可能低的水平,特别是对于仅用于验证唯一性的集合。
【问题讨论】:
你的意思是SQL计数大于1,值不唯一?方案2中,重复的值不会被加载到MongoDB中,可以吗? 不,我的意思是 SQL 计数大于 0。如果它的 1 表示条目已经存在,所以我不应该添加重复项。对于解决方案 2,如果 mongo 不允许我添加重复项也没关系,因为这正是我想要的。 【参考方案1】:我建议解决方案 1,即使用复合索引并使用两个不同的属性 key1 和 key2
db.yourCollection.ensureIndex( "key1": 1, "key2": 1 , unique: true )
-
如果需要,您可以通过单个字段轻松搜索。也就是说,如果您只需要通过 key1 或 key2 进行搜索,那么使用复合索引会很容易。如果你用组合键创建
_id
,则很难按单个字段搜索。
在设计文档时,Mongo 中的文档大小最不被打扰。
如果在不久的将来您需要更改同一文档的键值相对于其他值,这将很容易。请记住,如果您在其他集合的文档中使用此文档的引用。
就您的可扩展性而言,_id 索引将是顺序的、易于分片的,并且您可以让 MongoDB 管理它。
如果您使用这些键进行搜索,那么它将使用该索引,否则它将使用您搜索所需的其他索引。
如果您仍然在考虑文档大小而不是搜索,那么您可以使用解决方案 1,让 _id 喜欢
_id:key1:<value1>,key2:<value2>
这样你也可以搜索特定的_id.key1。
更新:
是的,如果您关心的是文档大小而不是维护。如果您确定键在未来不会修改同一文档,并且如果它仍在修改并且在其他集合中没有引用,那么您可以使用解决方案 1。只需使用键作为对象而不是下划线 _
。如果将来需要,您也可以稍后添加更多密钥。
【讨论】:
感谢您的解决方案!您不认为复合索引会占用更多内存,而且还会有额外的 _id 索引,这是不必要的。在我的情况下,我不会查询单个键,因为集合只是为了确保 value1 + value2 不重复。 问题是我的数据库已经有很多占用内存的索引,所以我想将我的索引大小保持在尽可能低的范围内。 @umair:我已经更新了答案。如果您有更多疑虑,请告诉我 @SomnathMuluk 我可能错了,但您似乎在答案中互换了解决方案 1 和解决方案 2。如果有请指正 @DhruvanGanesh:已更正。【参考方案2】:我认为解决方案 2 更适合满足您的要求。生成 MongoDB 的 _id 值是绝对可以的。大多数应用程序确实使用 UUID 填充 _id 值。在您的情况下,假设此集合主要用于验证唯一性(即临时表的种类)或查找目的,则为 _id 值连接值 1 和 2 是有意义的。
解决方案 1 很昂贵,因为它需要额外的索引。同样,这取决于您是要使用此集合来单独验证唯一性目的还是将其用于其他用例。
请注意,您需要创建唯一的复合索引,以便它不允许插入重复值的数据。
【讨论】:
以上是关于自定义 MongoDB 对象 _id 与复合索引的主要内容,如果未能解决你的问题,请参考以下文章