我有这个doc结构:
{
"key": {
"a": Int32,
"b": String
}
}
key
上的唯一索引和key.a
和key.b
上的索引(非唯一)。
然而,这个查询扫描(slooow):
{"key.a": 456213154}
并且此查询不会:
{"key": {
"a": 456213154,
"b": {"$exists": true}
}}
为什么这是必要的,应该是吗?
(我应该提到这是v2.0.3)
编辑:添加解释:
> db.collection.find({"key.a": 456213154}).explain()
{
"cursor" : "BtreeCursor key.a_1",
"nscanned" : 10962,
"nscannedObjects" : 10962,
"n" : 10962,
"millis" : 20,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
"key.a" : [
[
456213154,
456213154
]
]
}
}
> db.collection.find({"key": {"a": 456213154, "b": {"$exists":true}}}).explain()
{
"cursor" : "BtreeCursor key_1",
"nscanned" : 0,
"nscannedObjects" : 0,
"n" : 0,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
"key" : [
[
{
"a" : 456213154,
"b" : {
"$exists" : true
}
},
{
"a" : 456213154,
"b" : {
"$exists" : true
}
}
]
]
}
}
编辑:我尝试删除两个非唯一索引(key.a_1
和key.b_1
)以查看是否可能损害了查询。它不是:
> db.collection.find({"key.a": 456213154}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 23240518,
"nscannedObjects" : 23240518,
"n" : 10962,
"millis" : 15047,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
答案 0 :(得分:4)
您的explain()
输出表明:
有10962个对象key.a : 456213154
。您的db.collection.find({"key.a": 456213154})
查询使用了key.a
上的索引,并返回了10962个对象。
您的收藏集中有0个对象key.a : 456213154
且key.b : { $exists : true }
。 db.collection.find({"key": {"a": 456213154, "b": {"$exists":true}}})
查询确实在密钥上使用了您的索引。
查看每个查询的n
值 - 这是返回的数字;和cursor
值 - 如果使用索引,则为BtreeCursor
。在这种情况下,为什么第一个查询需要更长的时间才有意义,因为它有更多的对象要返回。
您确定key.a : 456213154
值的文档还有key.b
个值吗?
编辑:
使用$exists
参数的查询是检查嵌入文档中存在的错误语法。
尝试db.collection.find({ "key.a" : 456213154, "key.b" : { "$exists" : true } })
。