Same query with different execution time in mongodb - mongodb

I've executed one and the same query several times and the execution time differ from about a second to more than 20 seconds.
MongoDB version is 3.2.10.
Below is the output from explain method of a fast and a slow query.
Fast query:
{
"executionTimeMillis": 309,
"allPlansExecution": [
{
"shardName": "sh001-rs",
"allPlans": []
}
],
"totalKeysExamined": 18478,
"nReturned": 15096,
"executionStages": {
"executionTimeMillis": 309,
"shards": [
{
"shardName": "sh001-rs",
"executionSuccess": true,
"executionStages": {
"needYield": 0,
"docsExamined": 18378,
"saveState": 144,
"restoreState": 144,
"isEOF": 1,
"inputStage": {
"saveState": 144,
"isEOF": 1,
"seenInvalidated": 0,
"keysExamined": 18478,
"nReturned": 18378,
"invalidates": 0,
"keyPattern": {
"_id": 1
},
"isUnique": true,
"needTime": 99,
"isMultiKey": false,
"executionTimeMillisEstimate": 30,
"dupsTested": 0,
"restoreState": 144,
"direction": "forward",
"indexName": "_id_",
"isSparse": false,
"advanced": 18378,
"stage": "IXSCAN",
"dupsDropped": 0,
"needYield": 0,
"isPartial": false,
"indexBounds": {
"_id": []
},
"works": 18478,
"indexVersion": 1
},
"nReturned": 15096,
"needTime": 3381,
"filter": {
"available": {
"$gt": 0
}
},
"executionTimeMillisEstimate": 180,
"alreadyHasObj": 0,
"invalidates": 0,
"works": 18478,
"advanced": 15096,
"stage": "FETCH"
}
}
],
"nReturned": 15096,
"totalKeysExamined": 18478,
"totalChildMillis": 251,
"totalDocsExamined": 18378,
"stage": "SINGLE_SHARD"
},
"totalDocsExamined": 18378
}
Slow query:
{
"executionTimeMillis": 16139,
"allPlansExecution": [
{
"shardName": "sh001-rs",
"allPlans": []
}
],
"totalKeysExamined": 18478,
"nReturned": 15096,
"executionStages": {
"executionTimeMillis": 16139,
"shards": [
{
"shardName": "sh001-rs",
"executionSuccess": true,
"executionStages": {
"needYield": 0,
"docsExamined": 18378,
"saveState": 677,
"restoreState": 677,
"isEOF": 1,
"inputStage": {
"saveState": 677,
"isEOF": 1,
"seenInvalidated": 0,
"keysExamined": 18478,
"nReturned": 18378,
"invalidates": 0,
"keyPattern": {
"_id": 1
},
"isUnique": true,
"needTime": 99,
"isMultiKey": false,
"executionTimeMillisEstimate": 270,
"dupsTested": 0,
"restoreState": 677,
"direction": "forward",
"indexName": "_id_",
"isSparse": false,
"advanced": 18378,
"stage": "IXSCAN",
"dupsDropped": 0,
"needYield": 0,
"isPartial": false,
"indexBounds": {
"_id": []
},
"works": 18478,
"indexVersion": 1
},
"nReturned": 15096,
"needTime": 3381,
"filter": {
"available": {
"$gt": 0
}
},
"executionTimeMillisEstimate": 14518,
"alreadyHasObj": 0,
"invalidates": 0,
"works": 18478,
"advanced": 15096,
"stage": "FETCH"
}
}
],
"nReturned": 15096,
"totalKeysExamined": 18478,
"totalChildMillis": 16076,
"totalDocsExamined": 18378,
"stage": "SINGLE_SHARD"
},
"totalDocsExamined": 18378
}
The results from db.stats():
{
"raw" : {
"sh001-rs/host101-prod:27017,host102-prod:27018" : {
"db" : "records",
"collections" : 2,
"objects" : 124335,
"avgObjSize" : 48253.87085695902,
"dataSize" : 5999645033,
"storageSize" : 5008375808,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 17960960,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000018")
}
},
"sh002-rs/host101-prod:27018,host102-prod:27017" : {
"db" : "records",
"collections" : 2,
"objects" : 100643,
"avgObjSize" : 58044.42780918693,
"dataSize" : 5841765348,
"storageSize" : 4884041728,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 13737984,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000002")
}
},
"sh003-rs/host103-prod:27017,host104-prod:27018" : {
"db" : "records",
"collections" : 2,
"objects" : 191296,
"avgObjSize" : 31400.14176459518,
"dataSize" : 6006721519,
"storageSize" : 5967814656,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 32346112,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000012")
}
},
"sh004-rs/host103-prod:27018,host104-prod:27017" : {
"db" : "records",
"collections" : 2,
"objects" : 100904,
"avgObjSize" : 58444.951716482996,
"dataSize" : 5897329408,
"storageSize" : 5684531200,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 14114816,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff000000000000000c")
}
},
"sh005-rs/host105-prod:27017,host106-prod:27018" : {
"db" : "records",
"collections" : 16,
"objects" : 851626,
"avgObjSize" : 10900.204212882181,
"dataSize" : 9282897313,
"storageSize" : 7225233408,
"numExtents" : 0,
"indexes" : 43,
"indexSize" : 31690752,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff000000000000000e")
}
},
"sh006-rs/host105-prod:27018,host106-prod:27017" : {
"db" : "records",
"collections" : 2,
"objects" : 100946,
"avgObjSize" : 58688.667386523484,
"dataSize" : 5924386218,
"storageSize" : 7723163648,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 13565952,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000059")
}
},
"sh007-rs/host107-prod:27017,host108-prod:27018" : {
"db" : "records",
"collections" : 2,
"objects" : 100988,
"avgObjSize" : 58563.519497366025,
"dataSize" : 5914212707,
"storageSize" : 4643889152,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 14073856,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff000000000000000c")
}
},
"sh008-rs/host107-prod:27018,host108-prod:27017" : {
"db" : "records",
"collections" : 2,
"objects" : 100747,
"avgObjSize" : 58695.07362005817,
"dataSize" : 5913352582,
"storageSize" : 4877357056,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 13676544,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000002")
}
},
"sh009-rs/host109-prod:27017,host110-prod:27018" : {
"db" : "records",
"collections" : 4,
"objects" : 69101,
"avgObjSize" : 152884.28821580007,
"dataSize" : 10564457200,
"storageSize" : 16441020352,
"numExtents" : 32,
"indexes" : 17,
"indexSize" : 26171376,
"fileSize" : 19251855360,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000000")
}
},
"sh010-rs/host110-prod:27017,host113-prod:27018" : {
"db" : "records",
"collections" : 4,
"objects" : 69148,
"avgObjSize" : 152176.07311852838,
"dataSize" : 10522671104,
"storageSize" : 16439971776,
"numExtents" : 32,
"indexes" : 17,
"indexSize" : 26269488,
"fileSize" : 19251855360,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000002")
}
},
"sh011-rs/host109-prod:27018,host111-prod:27017" : {
"db" : "records",
"collections" : 2,
"objects" : 77687,
"avgObjSize" : 75111.53102835738,
"dataSize" : 5835189511,
"storageSize" : 5171572736,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 9543680,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000002")
}
},
"sh012-rs/host114-prod:27017,host115-prod:27018" : {
"db" : "records",
"collections" : 4,
"objects" : 91151,
"avgObjSize" : 115459.23068315213,
"dataSize" : 10524224336,
"storageSize" : 16454213568,
"numExtents" : 32,
"indexes" : 17,
"indexSize" : 42793184,
"fileSize" : 19251855360,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000028")
}
},
"sh013-rs/host114-prod:27018,host115-prod:27017" : {
"db" : "records",
"collections" : 2,
"objects" : 99992,
"avgObjSize" : 58494.27406192495,
"dataSize" : 5848959452,
"storageSize" : 6180712448,
"numExtents" : 0,
"indexes" : 17,
"indexSize" : 13615104,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff00000000000000a5")
}
},
"sh014-rs/host111-prod:27018,host113-prod:27017" : {
"db" : "records",
"collections" : 4,
"objects" : 91498,
"avgObjSize" : 114842.1660801329,
"dataSize" : 10507828512,
"storageSize" : 16454213568,
"numExtents" : 32,
"indexes" : 17,
"indexSize" : 42646016,
"fileSize" : 19251855360,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000004")
}
}
},
"objects" : 2170062,
"avgObjSize" : 48193.523844940835,
"dataSize" : 104583640243,
"storageSize" : 123156111104,
"numExtents" : 128,
"indexes" : 264,
"indexSize" : 312205824,
"fileSize" : 77007421440,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"ok" : 1
}
I've noticed that it is mainly the number of "saveState" and "restoreState" that differ. What could be the possible reason for this execution time variance?
Thanks in advance.

I don't know if this is sufficient as an answer for you, but it is possible to get different numbers when running the same query.
In depends on:
how many other operations are happening at the moment on your server
are the requested documents in memory (RAM) in this case the index.
Here you can also find the documentation for the output of your explain()

Related

MongoDB efficient way to search for objectId field with null using Index?

I am trying to find an efficient way to search for items in which specific field is null.
In the MongoDB, I have folder schema which has parent field of its parent folder's ObjectId and parent is indexed. For root folders, parent fields are null.
When I try to find all the root folders with parent:null, explain displays indexOnly: false
db.folders.find({parent: null}, {parent: 1, _id: 0}).explain()
{
"cursor" : "BtreeCursor parent_1",
"isMultiKey" : false,
"n" : 126,
"nscannedObjects" : 126,
"nscanned" : 126,
"nscannedObjectsAllPlans" : 126,
"nscannedAllPlans" : 126,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"parent" : [
[
null,
null
]
]
},
"server" : "c268.candidate.36:10268",
"filterSet" : false,
"stats" : {
"type" : "PROJECTION",
"works" : 128,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 126,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"children" : [
{
"type" : "KEEP_MUTATIONS",
"works" : 128,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 126,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"children" : [
{
"type" : "FETCH",
"works" : 128,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 126,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 126,
"children" : [
{
"type" : "IXSCAN",
"works" : 127,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 126,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ parent: 1.0 }",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['parent']: [null, null]",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 126,
"children" : []
}
]
}
]
}
]
}
}
I tried to use $type to find any ones which parent folder is not ObjectId. But still indexOnly:false.
db.folders.find({parent: {$ne: {$type: 7}}}, {parent: 1, _id: 0}).explain()
"indexOnly": false
Is there a way to search null value only using index? If not, is there a better value to store instead of null to be able to search with index?
Additional
example of root folder
{
"_id" : ObjectId("55a04a2d754971030059b7ad"),
"active" : true,
"modified" : ISODate("2016-02-05T22:30:08.053Z"),
"created" : ISODate("2015-07-10T22:41:49.009Z"),
"user" : ObjectId("54d3ae187a738c0300f59e61"),
"name" : "2nd Grade",
"parent" : null,
"clientModified" : ISODate("2016-02-05T22:30:07.872Z"),
"userCreated" : ISODate("2015-07-10T22:41:48.328Z"),
"ancestors" : [],
"__v" : 2
}
example of child folder
{
"_id" : ObjectId("56d0b4edb6f05e03009bcabc"),
"active" : true,
"modified" : ISODate("2016-02-26T20:26:21.328Z"),
"created" : ISODate("2016-02-26T20:26:21.328Z"),
"user" : ObjectId("54d3ae187a738c0300f59e61"),
"name" : "music",
"parent" : ObjectId("55a04a2d754971030059b7ad"),
"clientModified" : ISODate("2016-02-26T20:26:20.398Z"),
"userCreated" : ISODate("2016-02-26T20:26:20.398Z"),
"ancestors" : [
ObjectId("55a04a2d754971030059b7ad")
],
"__v" : 0
}
db.folders.getIndexes()
{
"0" : {
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "app29099188.folders"
},
"1" : {
"v" : 1,
"key" : {
"user" : 1,
"_fts" : "text",
"_ftsx" : 1
},
"name" : "user_1_name_text",
"ns" : "app29099188.folders",
"background" : true,
"safe" : null,
"weights" : {
"name" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 2
},
"2" : {
"v" : 1,
"key" : {
"user" : 1,
"parent" : 1
},
"name" : "user_1_parent_1",
"ns" : "app29099188.folders",
"background" : true,
"safe" : null
},
"3" : {
"v" : 1,
"key" : {
"parent" : 1.0000000000000000
},
"name" : "parent_1",
"ns" : "app29099188.folders"
}
}
After comment - update:
The way to eliminate docScan is to have a value in parent field. It can be zeroed objectId or just "/" as a root.
db.satoko.insert({"test":"sdsf", parent: "/"})
db.satoko.insert({"test":"sds33f", parent: "/"})
db.satoko.insert({"parent":ObjectId("56d8b2879bd059e7247a6096"), "test":"sdsf"})
explain results:
db.satoko.find({parent:{$eq:"/"} }, {parent: 1, _id: 0}).explain("allPlansExec
ution")
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.satoko",
"indexFilterSet" : false,
"parsedQuery" : {
"parent" : {
"$eq" : "/"
}
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"parent" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"parent" : 1
},
"indexName" : "parent_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"parent" : [
"[\"/\", \"/\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 2,
"executionTimeMillis" : 0,
"totalKeysExamined" : 2,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 2,
"executionTimeMillisEstimate" : 0,
"works" : 3,
"advanced" : 2,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"parent" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 2,
"executionTimeMillisEstimate" : 0,
"works" : 3,
"advanced" : 2,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"parent" : 1
},
"indexName" : "parent_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"parent" : [
"[\"/\", \"/\"]"
]
},
"keysExamined" : 2,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
},
"allPlansExecution" : [ ]
},
"serverInfo" : {
"host" : "greg",
"port" : 27017,
"version" : "3.2.3",
"gitVersion" : "b326ba837cf6f49d65c2f85e1b70f6f31ece7937"
},
"ok" : 1
}

count slow in mongodb 2.6.8

I've a find request which takes 0.031sec, but when I try to do the same request with a count, it takes over 1sec.
I tried different indexes but it's always the same problem.
Count is still slow.
any idea?
volume
1600000 documents
My request
db.books.find(
{
"categories" : { $eq : null},
"theme" : "comics"
}
)
My Index
{
"categories" : 1,
"theme" : 1
}
Explain
{
"cursor" : "BtreeCursor categories_1_theme_1",
"isMultiKey" : false,
"n" : 353912,
"nscannedObjects" : 353912,
"nscanned" : 353912,
"nscannedObjectsAllPlans" : 354821,
"nscannedAllPlans" : 354821,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 2771,
"nChunkSkips" : 0,
"millis" : 1111,
"indexBounds" : {
"theme" : [
[
"comics",
"comics"
]
],
"categories" : [
[
null,
null
]
]
},
"server" : "xxxmongoxxx:27017",
"filterSet" : false,
"stats" : {
"type" : "KEEP_MUTATIONS",
"works" : 353913,
"yields" : 2771,
"unyields" : 2771,
"invalidates" : 0,
"advanced" : 353912,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"children" : [
{
"type" : "FETCH",
"works" : 353913,
"yields" : 2771,
"unyields" : 2771,
"invalidates" : 0,
"advanced" : 353912,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 353912,
"children" : [
{
"type" : "IXSCAN",
"works" : 353913,
"yields" : 2771,
"unyields" : 2771,
"invalidates" : 0,
"advanced" : 353912,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ categories: 1, theme: 1 }",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['categories']: [\"comics\", \"comics\"], field #1['theme']: [null, null]",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 353912,
"children" : []
}
]
}
]
}
}

Why indexOnly==false

I have a collection with index:
{
"UserId" : 1,
"ShareId" : 1,
"ParentId" : 1,
"DeletedDate" : 1
}
If I making query:
db.Files.find({ "UserId" : ObjectId("5450d837f32a1e098c844e2a"),
"ShareId" : ObjectId("5450d879f32a1e098c844e94"),
"ParentId" : ObjectId("5450d8af6a092a0b74a44026"),
"DeletedDate":null},
{_id:0, ShareId:1}).explain()
output says that "indexOnly" : false:
{
"cursor" : "BtreeCursor UserId_1_ShareId_1_ParentId_1_DeletedDate_1",
"isMultiKey" : false,
"n" : 2120,
"nscannedObjects" : 2120,
"nscanned" : 2120,
"nscannedObjectsAllPlans" : 2318,
"nscannedAllPlans" : 2320,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 21,
"nChunkSkips" : 0,
"millis" : 42,
"indexBounds" : {
"UserId" : [
[
ObjectId("5450d837f32a1e098c844e2a"),
ObjectId("5450d837f32a1e098c844e2a")
]
],
"ShareId" : [
[
ObjectId("5450d879f32a1e098c844e94"),
ObjectId("5450d879f32a1e098c844e94")
]
],
"ParentId" : [
[
ObjectId("5450d8af6a092a0b74a44026"),
ObjectId("5450d8af6a092a0b74a44026")
]
],
"DeletedDate" : [
[
null,
null
]
]
},
"server" : "mongowecntprod:27017",
"filterSet" : false,
"stats" : {
"type" : "PROJECTION",
"works" : 2124,
"yields" : 21,
"unyields" : 21,
"invalidates" : 0,
"advanced" : 2120,
"needTime" : 0,
"needFetch" : 2,
"isEOF" : 1,
"children" : [
{
"type" : "KEEP_MUTATIONS",
"works" : 2124,
"yields" : 21,
"unyields" : 21,
"invalidates" : 0,
"advanced" : 2120,
"needTime" : 1,
"needFetch" : 2,
"isEOF" : 1,
"children" : [
{
"type" : "FETCH",
"works" : 2124,
"yields" : 21,
"unyields" : 21,
"invalidates" : 0,
"advanced" : 2120,
"needTime" : 1,
"needFetch" : 2,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 2120,
"children" : [
{
"type" : "IXSCAN",
"works" : 2121,
"yields" : 21,
"unyields" : 21,
"invalidates" : 0,
"advanced" : 2120,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ UserId: 1, ShareId: 1, ParentId: 1, DeletedDate: 1 }",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['UserId']: [ObjectId('5450d837f32a1e098c844e2a'), ObjectId('5450d837f32a1e098c844e2a')], field #1['ShareId']: [ObjectId('5450d879f32a1e098c844e94'), ObjectId('5450d879f32a1e098c844e94')], field #2['ParentId']: [ObjectId('5450d8af6a092a0b74a44026'), ObjectId('5450d8af6a092a0b74a44026')], field #3['DeletedDate']: [null, null]",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 2120,
"children" : []
}
]
}
]
}
]
}
}
but if I making query without DeletedDate:
db.Files.find({ "UserId" : ObjectId("5450d837f32a1e098c844e2a"),
"ShareId" : ObjectId("5450d879f32a1e098c844e94"),
"ParentId" : ObjectId("5450d8af6a092a0b74a44026")},
{_id:0, ShareId:1}).explain()
then "indexOnly" is true.
How I can change first query to making indexOnly=true?
Let me give you a simple example that will hopefully demonstrate what you're seeing when you are querying for a field being null:
db.nullexplain.find()
{ "_id" : ObjectId("5456759f51a9d5271dc55bba"), "a" : 1 }
{ "_id" : ObjectId("545675a251a9d5271dc55bbb"), "a" : null }
{ "_id" : ObjectId("545675a551a9d5271dc55bbc") }
db.nullexplain.ensureIndex({a:1})
db,nullexplain.count({a:1}).count()
1
db.nullexplain.count({a:null}).count()
2
Do you see the issue? When "a" is present and explicitly set to null, it's indexed as null.
When "a" is not present in the document, it's also indexed as null.
When you query:
db.nullexplain.find({a:null},{_id:0,a:1})
{ "a" : null }
{ }
How can we derive from the index only whether the return document should have the field "a" set to null or if the field should not be present at all?
The answer is we cannot and therefore we must examine the document itself.
db.nullexplain.find({a:null},{_id:0,a:1}).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 3,
"nscanned" : 3,
"nscannedObjectsAllPlans" : 3,
"nscannedAllPlans" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 3,
"server" : "Asyas-MacBook-Pro.local:27017",
"filterSet" : false
}
Hope this helps you understand why querying for DeletedDate:null has to check the document and cannot be answered from the index.

MongoDb Java driver iterating over cursor very slow

first of all, I googled and searched this forum but found no direct answer to my question, so I decided to ask a new one.
I have a "sensors" collection containing about 20k sensors. My query is very simple:
QueryBuilder qb = new QueryBuilder().and(
new QueryBuilder().put("q1").lessThan(rb).get(),
new QueryBuilder().put("q3").greaterThan(ra).get()
);
DBCursor cursor = sensorColl.find(qb.get());
begin = System.currentTimeMillis();
while (cursor.hasNext()) {
cursor.next();
}
long totalSearchTime = System.currentTimeMillis()-begin;
logger.debug("totalSearchTime: {}", totalSearchTime);
which shows the totalSearchTime is 316647ms! I repeated this code snippet multiple time and on average it takes similar time to complete. Here is the explain() for the query:
{
"cursor" : "BtreeCursor q1_1_q3_-1",
"isMultiKey" : false,
"n" : 16905,
"nscannedObjects" : 16905,
"nscanned" : 16905,
"nscannedObjectsAllPlans" : 16905,
"nscannedAllPlans" : 16905,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 132,
"nChunkSkips" : 0,
"millis" : 102,
"indexBounds" : {
"q1" : [
[
-Infinity,
30
]
],
"q3" : [
[
Infinity,
10
]
]
},
"server" : "localhost:27017",
"filterSet" : false,
"stats" : {
"type" : "FETCH",
"works" : 16907,
"yields" : 132,
"unyields" : 132,
"invalidates" : 0,
"advanced" : 16905,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 0,
"children" : [
{
"type" : "IXSCAN",
"works" : 16906,
"yields" : 132,
"unyields" : 132,
"invalidates" : 0,
"advanced" : 16905,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ q1: 1.0, q3: -1.0 }",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['q1']: [-inf.0, 30.0), field #1['q3']: [inf.0, 10.0)",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 16905,
"children" : []
}
]
}
}
And here is the stats()
{
"ns" : "sensor_db.sensors",
"count" : 16999,
"size" : 272697744,
"avgObjSize" : 16041,
"storageSize" : 315080704,
"numExtents" : 15,
"nindexes" : 2,
"lastExtentSize" : 84451328,
"paddingFactor" : 1.006,
"systemFlags" : 0,
"userFlags" : 1,
"totalIndexSize" : 1888656,
"indexSizes" : {
"_id_" : 981120,
"q1_1_q3_-1" : 907536
},
"ok" : 1
}
I run my app in my test system (my laptop) with Intel(R) Core(TM)2 Duo CPU T7100 # 1.80GHz, 800 MHz and 1.5GB RAM (of which ~700MB are free at the time the query was run). The disk space is 58GB free so that is a lot.
I hope those information is enough for analysis. Thanks a lot for any suggestion!

Why so many scanned Objects?

I have a table with the following objects:
> db.shapes.find()
{ "_id" : "P1", "amenity" : "restaurant", "shape" : { "type" : "Point",
"coordinates" : [ 2, 2 ] } }
{ "_id" : "P2", "amenity" : "restaurant", "shape" : { "type" : "Point",
"coordinates" : [ 2, 4 ] } }
{ "_id" : "P3", "amenity" : "police", "shape" : { "type" : "Point",
"coordinates" : [ 4, 2 ] } }
{ "_id" : "P4", "amenity" : "police", "shape" : { "type" : "Point",
"coordinates" : [ 4, 4 ] } }
The explain() on the following query gives a strange (in my opinion) result:
> db.shapes.find({shape:{$nearSphere:{$geometry:{type: "Point", coordinates:
[0,0]}}}}, {id:1, amenity:1}).limit(2).explain()
{
"cursor" : "S2NearCursor",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 22,
"nscanned" : 22,
"nscannedObjectsAllPlans" : 22,
"nscannedAllPlans" : 22,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 1,
"indexBounds" : {
},
"server" : "DBTest:27017",
"filterSet" : false
}
Why there are this much objects scanned ? I mean, the table only has 4
objects and mongodb scans 22 ?
I am thankful for any explanation.
Bye, Andre
> db.shapes.find({shape:{$nearSphere:{$geometry:{type: "Point", coordinates:
... [0,0]}}}}, {id:1, amenity:1}).limit(2).explain(1)
{
"cursor" : "S2NearCursor",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 22,
"nscanned" : 22,
"nscannedObjectsAllPlans" : 22,
"nscannedAllPlans" : 22,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 1,
"indexBounds" : {
},
"allPlans" : [
{
"cursor" : "S2NearCursor",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 22,
"nscanned" : 22,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
}
}
],
"server" : "DBTest:27017",
"filterSet" : false,
"stats" : {
"type" : "LIMIT",
"works" : 22,
"yields" : 0,
"unyields" : 0,
"invalidates" : 0,
"advanced" : 2,
"needTime" : 20,
"needFetch" : 0,
"isEOF" : 1,
"children" : [
{
"type" : "PROJECTION",
"works" : 22,
"yields" : 0,
"unyields" : 0,
"invalidates" : 0,
"advanced" : 2,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 0,
"children" : [
{
"type" : "GEO_NEAR_2DSPHERE",
"works" : 22,
"yields" : 0,
"unyields" : 0,
"invalidates" : 0,
"advanced" : 2,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 0,
"children" : [ ]
}
]
}
]
}
}
It looks like you are using version 2.4 and are running into https://jira.mongodb.org/browse/SERVER-12231 which was fixed for version 2.6. If you upgrade, it's likely you will no longer see the bogus nscanned numbers in explain() output.