【发布时间】:2019-02-04 12:51:13
【问题描述】:
我试图理解为什么 Mongo 不能在我使用 $nin 的查询中使用覆盖索引,以及如何解决它。我的问题是复合索引,但它也发生在简单索引上。
拿一个简单的文件:
{b: "text1"}
还有一个简单的索引:
{
"v" : 1,
"key" : {
"b" : 1
},
"name" : "b_1",
"ns" : "mytest"
}
我认为是一个简单的count() 查询:
db.mytest.count( {b: $nin: [ "foo" ]}, {b:1, _id:0} )
winningPlan 意外包含FETCH:
"winningPlan" : {
"stage" : "COUNT",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"b" : 1
},
"indexName" : "b_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"b" : [
"[MinKey, \"foo\")",
"(\"foo\", MaxKey]"
]
}
}
}
}
但是对于一个简单的相等条件,它使用COUNT_SCAN(如预期的那样):
> db.mytest.count( {b: "bar" }, {b:1, _id:0} )
"winningPlan" : {
"stage" : "COUNT",
"inputStage" : {
"stage" : "COUNT_SCAN",
"keyPattern" : {
"b" : 1
},
"indexName" : "b_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1
}
},
为了让事情更有趣,find() 而不是 count() 不会查看任何文档:
> db.mytest.find({b:{ $nin: [ 3 ] }}, {b:1, _id:0})
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"b" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"b" : 1
},
"indexName" : "b_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"b" : [
"[MinKey, 3.0)",
"(3.0, MaxKey]"
]
}
}
}
为什么 Mongo 需要 FETCH 和 $nin?它应该能够完全从索引中实现这一点。
【问题讨论】:
-
可能与query selectivity 的
$nin相关。