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(这将创建更小的索引并浪费更少的空间)并保留您的KeyAKeyB 和@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 对象 _id 与复合索引

Mongodb复合索引 - 也内置_id排序?

Mongodb 复合 2dsphere 索引无法按预期工作

MongoDB 复合索引到 Kibana elasticsearch

MongoDB——索引类型之复合索引(Compound Index)

MongoDB——索引类型之复合索引(Compound Index)