Is that a reasonable explanation, when all other queries against this
index ("Flags" : null, "Flags" : 1 etc) are extremely fast? There are
about 5 different values of Flags in the entire collection, so the
cardinality of Flags is very low.
I tried making yet another new collection and managed to recreate this
issue with the following code.
> for (var i = 1; i <= 1000000; i++) db.test.save({x : i+1000000})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [1]})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [1,3]})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [1,2,3]})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [2,3]})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [2]})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [3]})
> for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags : [1,2]})
> db.test.ensureIndex({ Flags : 1})
> db.test.find({ Flags : { $type : 10}}).limit(1).explain()
{
"cursor" : "BtreeCursor Flags_1",
"nscanned" : 1000000,
"nscannedObjects" : 1000000,
"n" : 0,
"millis" : 1820,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"Flags" : [
[
null,
null
]
]
}
}
> db.test.find({ Flags : null}).limit(1).explain()
{
"cursor" : "BtreeCursor Flags_1",
"nscanned" : 1,
"nscannedObjects" : 1,
"n" : 1,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"Flags" : [
[
null,
null
]
]
}
}
> db.test.find({ Flags : 1}).limit(1).explain()
{
"cursor" : "BtreeCursor Flags_1",
"nscanned" : 1,
"nscannedObjects" : 1,
"n" : 1,
"millis" : 6,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"Flags" : [
[
1,
1
]
]
}
}
It seems like { $type : 10} scans all documents that doesn't have the
field and tries to check that for null. Is that the way it's supposed
to be?
I'm not sure what the difference is between this collection and the
one i made earlier. That example didn't have more than three values of
Flags (not set, null and [1]). That may be it..
Another example: (the only difference is that I insert 100 records
with Flags set to null aswell). Remember to drop "test" between these
examples.
for (var i = 1; i <= 1000000; i++) db.test.save({x : i+1000000})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[1]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[1,3]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[1,2,3]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[2,3]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[2]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[3]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
[1,2]})
for (var i = 1; i <= 100; i++) db.test.save({x : i+1000000, Flags :
null})
db.test.ensureIndex({ Flags : 1})
db.test.find({ Flags : { $type : 10}}).limit(1).explain()
{
"cursor" : "BtreeCursor Flags_1",
"nscanned" : 787654,
"nscannedObjects" : 787654,
"n" : 1,
"millis" : 1513,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"Flags" : [
[
null,
null
]
]
}
}
787654 seems like a very random number of documents to scan. And for
some reason the presence of those 100 documents with Flags : null,
changes nscanned from 1M to ~800k
I'm sure there's a reason for this behaviour but I'm struggling to
understand it.
/Anders
> This is a continuation fromhttp://
groups.google.com/group/mongodb-user/browse_thread/thread/f342...