MongoDB中复合_id的预期行为?
Posted
技术标签:
【中文标题】MongoDB中复合_id的预期行为?【英文标题】:Expected Behaviour of Compound _id in MongoDB? 【发布时间】:2011-08-30 16:21:06 【问题描述】:我有一个包含 3 个数字属性的复合 _id:
_id": “键A”:0, “键B”:0, “KeyC”:0
有问题的数据库有 200 万个 KeyA 相同的值和 500k 个 KeyB 相同值的集群。
我的理解是我可以使用以下命令有效地查询 KeyA 和 KeyB:
find( "_id.KeyA" : 1, "_id.KeyB": 3 ).limit(100)
当我解释这个查询时,结果是:
"cursor" : "BasicCursor",
"nscanned" : 1000100,
"nscannedObjects" : 1000100,
"n" : 100,
"millis" : 1592,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" :
没有limit()的结果是:
"cursor" : "BasicCursor",
"nscanned" : 2000000,
"nscannedObjects" : 2000000,
"n" : 500000,
"millis" : 3181,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" :
据我了解,BasicCursor 意味着索引已被忽略,并且两个查询的执行时间都很长——即使我只请求了 100 条记录,它也需要大约 1.5 秒。我打算使用限制来实现分页,但这显然太慢了。
命令:
find( "_id.KeyA" : 1, "_id.KeyB": 3, , "_id.KeyC": 1000 )
正确使用 BtreeCursor 并快速执行,提示复合 _id 正确。
我正在使用 MongoDb 的 1.8.3 版本。如果我看到预期的行为或者我误解了如何使用/查询复合索引,有人可以澄清一下吗?
谢谢, 保罗。
【问题讨论】:
【参考方案1】:索引不是复合索引,而是_id
字段的整个值的索引。 MongoDB 不会查看索引字段,而是使用字段的原始 BSON 表示进行比较(如果我正确阅读了文档)。
要执行您想要的操作,您需要一个超过 _id.KeyA: 1, _id.KeyB: 1, _id.KeyC: 1
的实际复合索引(这也应该是一个唯一索引)。由于您不能在_id
上没有索引,因此最好将其保留为ObjectId
(这将创建更小的索引并浪费更少的空间)并保留您的KeyA
、KeyB
和@987654327 @ 字段作为文档的属性。例如。 _id: ObjectId("xyz..."), KeyA: 1, KeyB: 2, KeyB: 3
【讨论】:
Theo - 谢谢,虽然你的回答与 mstreams 基本相同,但我接受了你的回答,因为你明确指出 _id 字段没有给我一个复合索引(这是我的一点无法掌握)。我天真地假设如果我在自动索引的 _id 字段上创建了一个复合键,那么最终结果将是一个复合索引。你生活和学习。【参考方案2】:您需要一个单独的复合索引来表示您想要的行为。一般来说,我建议不要将对象用作 _id,因为键顺序在比较中很重要,因此 a:1, b:1 不等于 b:1, a:1。由于并非所有驱动程序都保留对象中的关键顺序,因此很容易通过执行以下操作来击中自己的脚:
db.foo.save(db.foo.findOne())
【讨论】:
以上是关于MongoDB中复合_id的预期行为?的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB 复合索引到 Kibana elasticsearch