$or:[{b:1},{b:2}]
doesn't use the index but
b:{$in:[1,2]}
does, showing that I'm not asking for anything that is fundamentally impossible with the given index.I confirmed this in 2.6.6 but could not find an open ticket about it – is this a known issue?
Test code:
use test;
db.createCollection(' indexTest');
for (var i=1; i<=10; i++) { for (var j=1; j<=10; j++) {db.indexTest.insert({ a:i, b:j }); } }
db.indexTest.ensureIndex({ a:1, b:1 });
db.indexTest.find({ a:4, $or:[{b:1},{b:2}] }).explain(); // uses index(a)
db.indexTest.find({ a:4, b:{$in:[1,2]} }).explain(); // uses index(a,b)
Output of the explain()s:
> db.indexTest.find({ a:4, $or:[{b:1},{b:3}] }).explain();
{
"cursor" : "BtreeCursor a_1_b_1",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 10,
"nscanned" : 10,
"nscannedObjectsAllPlans" : 10,
"nscannedAllPlans" : 10,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"a" : [
[
4,
4
]
],
"b" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "...",
"filterSet" : false
}
> db.indexTest.find({ a:4, b:{$in:[1,3]} }).explain();
{
"cursor" : "BtreeCursor a_1_b_1",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 2,
"nscanned" : 3,
"nscannedObjectsAllPlans" : 2,
"nscannedAllPlans" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"a" : [
[
4,
4
]
],
"b" : [
[
1,
1
],
[
3,
3
]
]
},
"server" : "...",
"filterSet" : false
}
The key is "given a fixed choice for a".
If you rewrite your query as {$or: [ {a:4, b:1}, {a:4,b:3} ]} I
believe you will see the index be used again.
The server ticket tracking the fact the optimizer doesn't rewrite the
query this way is SERVER-13732
Thanks for pointing me to the right ticket! One could argue that in addition to the options discussed there, the query could be rewritten to use $in where possible – if there were a rewrite engine. But obviously, the option of rephrasing the query is already available to the user, so it's not that big a deal.
댓글 없음:
댓글 쓰기