Monday, November 14, 2016

Mongodb explain() Query Analyzer and it's Verbosity

First creating 1 million documents:
> for(i=0; i<100; i++) { for(j=0; j<100; j++) {x = []; for(k=0; k<100; k++) { x.push({a:i, b:j, c:k, _id:(100*100*i+100*j+k) } ) }; db.example.insert(x) } }

BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 100,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})
>

We have added 1 million documents to the collection, colleciton look like:
> db.example.find()
{ "_id" : 0, "a" : 0, "b" : 0, "c" : 0 }
{ "_id" : 1, "a" : 0, "b" : 0, "c" : 1 }
{ "_id" : 2, "a" : 0, "b" : 0, "c" : 2 }
{ "_id" : 3, "a" : 0, "b" : 0, "c" : 3 }
{ "_id" : 4, "a" : 0, "b" : 0, "c" : 4 }
{ "_id" : 5, "a" : 0, "b" : 0, "c" : 5 }
{ "_id" : 6, "a" : 0, "b" : 0, "c" : 6 }
{ "_id" : 7, "a" : 0, "b" : 0, "c" : 7 }
{ "_id" : 8, "a" : 0, "b" : 0, "c" : 8 }
{ "_id" : 9, "a" : 0, "b" : 0, "c" : 9 }
{ "_id" : 10, "a" : 0, "b" : 0, "c" : 10 }
{ "_id" : 11, "a" : 0, "b" : 0, "c" : 11 }
{ "_id" : 12, "a" : 0, "b" : 0, "c" : 12 }
{ "_id" : 13, "a" : 0, "b" : 0, "c" : 13 }
{ "_id" : 14, "a" : 0, "b" : 0, "c" : 14 }
{ "_id" : 15, "a" : 0, "b" : 0, "c" : 15 }
{ "_id" : 16, "a" : 0, "b" : 0, "c" : 16 }
{ "_id" : 17, "a" : 0, "b" : 0, "c" : 17 }
{ "_id" : 18, "a" : 0, "b" : 0, "c" : 18 }
{ "_id" : 19, "a" : 0, "b" : 0, "c" : 19 }
Type "it" for more
> it
{ "_id" : 20, "a" : 0, "b" : 0, "c" : 20 }
{ "_id" : 21, "a" : 0, "b" : 0, "c" : 21 }
{ "_id" : 22, "a" : 0, "b" : 0, "c" : 22 }
{ "_id" : 23, "a" : 0, "b" : 0, "c" : 23 }
{ "_id" : 24, "a" : 0, "b" : 0, "c" : 24 }
{ "_id" : 25, "a" : 0, "b" : 0, "c" : 25 }
{ "_id" : 26, "a" : 0, "b" : 0, "c" : 26 }
{ "_id" : 27, "a" : 0, "b" : 0, "c" : 27 }
{ "_id" : 28, "a" : 0, "b" : 0, "c" : 28 }
{ "_id" : 29, "a" : 0, "b" : 0, "c" : 29 }
{ "_id" : 30, "a" : 0, "b" : 0, "c" : 30 }
{ "_id" : 31, "a" : 0, "b" : 0, "c" : 31 }
{ "_id" : 32, "a" : 0, "b" : 0, "c" : 32 }
{ "_id" : 33, "a" : 0, "b" : 0, "c" : 33 }
{ "_id" : 34, "a" : 0, "b" : 0, "c" : 34 }
{ "_id" : 35, "a" : 0, "b" : 0, "c" : 35 }
{ "_id" : 36, "a" : 0, "b" : 0, "c" : 36 }
{ "_id" : 37, "a" : 0, "b" : 0, "c" : 37 }
{ "_id" : 38, "a" : 0, "b" : 0, "c" : 38 }
{ "_id" : 39, "a" : 0, "b" : 0, "c" : 39 }

Now we are going to add indexes to the collection:
> db.example.createIndex({a:1, b:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
>

Creating another index on field b:
> db.example.createIndex({b:1})

> db.example.createIndex({b:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}

> db.example.getIndexes();
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "learn.example"
        },
        {
                "v" : 1,
                "key" : {
                        "a" : 1,
                        "b" : 1
                },
                "name" : "a_1_b_1",
                "ns" : "learn.example"
        },
        {
                "v" : 1,
                "key" : {
                        "b" : 1
                },
                "name" : "b_1",
                "ns" : "learn.example"
        }
]

Getting an explainable object:
> exp = db.example.explain()
Explainable(learn.example)

Now seeing what are the various operations you can do with exp:

> exp.help()
Explainable operations
        .aggregate(...) - explain an aggregation operation
        .count(...) - explain a count operation
        .distinct(...) - explain a distinct operation
        .find(...) - get an explainable query
        .findAndModify(...) - explain a findAndModify operation
        .group(...) - explain a group operation
        .remove(...) - explain a remove operation
        .update(...) - explain an update operation
Explainable collection methods
        .getCollection()
        .getVerbosity()
        .setVerbosity(verbosity)
It tells you all great thing you can do.

> exp.find({a:17, b:55}).sort({b:-1})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "$and" : [
                                {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                {
                                        "b" : {
                                                "$eq" : 55
                                        }
                                }
                        ]
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "a" : 1,
                                        "b" : 1
                                },
                                "indexName" : "a_1_b_1",
                                "isMultiKey" : false,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "backward",
                                "indexBounds" : {
                                        "a" : [
                                                "[17.0, 17.0]"
                                        ],
                                        "b" : [
                                                "[55.0, 55.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [
                        {
                                "stage" : "FETCH",
                                "filter" : {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "keyPattern" : {
                                                "b" : 1
                                        },
                                        "indexName" : "b_1",
                                        "isMultiKey" : false,
                                        "isUnique" : false,
                                        "isSparse" : false,
                                        "isPartial" : false,
                                        "indexVersion" : 1,
                                        "direction" : "backward",
                                        "indexBounds" : {
                                                "b" : [
                                                        "[55.0, 55.0]"
                                                ]
                                        }
                                }
                        }
                ]
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}
>

WinningPlan is what actually got chooses. We can see that it uses in IXSCAN and used a and b of the index and index used is a_1_b_1 which is an index on a,b. It's not a multi key index, direction is backword because of the sorting order. It shows the bound since we are looking for a single document so the bound is as:
"a" : ["[17.0, 17.0]"],
 "b" : ["[55.0, 55.0]"]
Also shows the rejectedPlans, where is shows it considered using an index only on b but turn out to be a worst choice so turn off this option so it didn't do it.

We could have also got the same thing rather then creating an explanable object first by using command:
> db.example.explain().find({a:17, b:55}).sort({b:-1});

In earlier version of mongodb the option by which you run explain is calling explain after the find:
> db.example.find({a:17, b:55}).sort({b:-1}).explain();

example.find() bring back a cursor with explain set on it, but the result is same when you see it in shell. 

Now why do mongodb change it up, why make a new approach of explanable object, so we change it because certain things won't return a cursor. For instance if I want to perform this old version, we cannot get an explain output:

> db.example.find({a:17, b:55}).sort({b:-1}).count().explain();
2016-11-12T19:34:34.909+0530 E QUERY    [thread1] TypeError: db.example.find(...).sort(...).count(...).explain is not a function :
@(shell):1:1

On the other hand if I use my explain object and I do a count on that, I can actually get an explain output:
> exp.count()
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "winningPlan" : {
                        "stage" : "COUNT"
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}
>

Now looking explainable object where it doesn't use an index.
>  exp.find({c:200})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "c" : {
                                "$eq" : 200
                        }
                },
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "c" : {
                                        "$eq" : 200
                                }
                        },
                        "direction" : "forward"
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}

This can the whole collection as there is no index on c.

> var cursor = db.example.find({a:99});
> cursor.explain();
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "a" : {
                                "$eq" : 99
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "a" : 1,
                                        "b" : 1
                                },
                                "indexName" : "a_1_b_1",
                                "isMultiKey" : false,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "a" : [
                                                "[99.0, 99.0]"
                                        ],
                                        "b" : [
                                                "[MinKey, MaxKey]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}

I can actually call next on the cursor if I want the result.
> cursor.next()
{ "_id" : 990000, "a" : 99, "b" : 0, "c" : 0 }
> cursor.next()
{ "_id" : 990001, "a" : 99, "b" : 0, "c" : 1 }
> cursor.next()
{ "_id" : 990002, "a" : 99, "b" : 0, "c" : 2 }

executionStats verbosity mode of explain:

Creating explanable object with executionStats option:

> exp = db.example.explain("executionStats")
Explainable(learn.example)

Now running our query on a and b:

> exp.find({a:17, b:55})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "$and" : [
                                {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                {
                                        "b" : {
                                                "$eq" : 55
                                        }
                                }
                        ]
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "a" : 1,
                                        "b" : 1
                                },
                                "indexName" : "a_1_b_1",
                                "isMultiKey" : false,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "a" : [
                                                "[17.0, 17.0]"
                                        ],
                                        "b" : [
                                                "[55.0, 55.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [
                        {
                                "stage" : "KEEP_MUTATIONS",
                                "inputStage" : {
                                        "stage" : "FETCH",
                                        "filter" : {
                                                "a" : {
                                                        "$eq" : 17
                                                }
                                        },
                                        "inputStage" : {
                                                "stage" : "IXSCAN",
                                                "keyPattern" : {
                                                        "b" : 1
                                                },
                                                "indexName" : "b_1",
                                                "isMultiKey" : false,
                                                "isUnique" : false,
                                                "isSparse" : false,
                                                "isPartial" : false,
                                                "indexVersion" : 1,
                                                "direction" : "forward",
                                                "indexBounds" : {
                                                        "b" : [
                                                                "[55.0, 55.0]"
                                                        ]
                                                }
                                        }
                                }
                        }
                ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 100,
                "executionTimeMillis" : 162,
                "totalKeysExamined" : 100,
                "totalDocsExamined" : 100,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 100,
                        "executionTimeMillisEstimate" : 30,
                        "works" : 104,
                        "advanced" : 100,
                        "needTime" : 0,
                        "needYield" : 2,
                        "saveState" : 6,
                        "restoreState" : 6,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "docsExamined" : 100,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 100,
                                "executionTimeMillisEstimate" : 20,
                                "works" : 101,
                                "advanced" : 100,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 6,
                                "restoreState" : 6,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "keyPattern" : {
                                        "a" : 1,
                                        "b" : 1
                                },
                                "indexName" : "a_1_b_1",
                                "isMultiKey" : false,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "a" : [
                                                "[17.0, 17.0]"
                                        ],
                                        "b" : [
                                                "[55.0, 55.0]"
                                        ]
                                },
                                "keysExamined" : 100,
                                "dupsTested" : 0,
                                "dupsDropped" : 0,
                                "seenInvalidated" : 0
                        }
                }
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}
>

Once again we got the queryPlanner mode which tells us it is going to use a_1_b_1 index and shows the parse query. It also tells us the rejected plan and the rejected plan is to use the b index on this. But it doesn't tell what happen when it use all these which it is showing.

So the executionStats here will tell us the exectionstats of the winning plan and there are certain key item we must give attention to:

nReturned: 100 : number of document query actually return. 

"executionTimeMillis" : 162
Time for the query 162 millisecond

"totalKeysExamined" : 100
"totalDocsExamined" : 100
It tells us index worked preety well, we looked at 100 keys and we got 100 documents. 

Further in "inputStage" we can see number of documents returned at each stage. It shows the values index looked into in indexBounds, it shows indexName and keyPattern.

Now checking what happen if we do not have a_1_b_1 index. Dropping index:

> db.example.dropIndex({a:1, b:1})
{ "nIndexesWas" : 3, "ok" : 1 }
>

> exp.find({a:17, b:55})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "$and" : [
                                {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                {
                                        "b" : {
                                                "$eq" : 55
                                        }
                                }
                        ]
                },
                "winningPlan" : {
                        "stage" : "KEEP_MUTATIONS",
                        "inputStage" : {
                                "stage" : "FETCH",
                                "filter" : {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "keyPattern" : {
                                                "b" : 1
                                        },
                                        "indexName" : "b_1",
                                        "isMultiKey" : false,
                                        "isUnique" : false,
                                        "isSparse" : false,
                                        "isPartial" : false,
                                        "indexVersion" : 1,
                                        "direction" : "forward",
                                        "indexBounds" : {
                                                "b" : [
                                                        "[55.0, 55.0]"
                                                ]
                                        }
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 100,
                "executionTimeMillis" : 661,
                "totalKeysExamined" : 10000,
                "totalDocsExamined" : 10000,
                "executionStages" : {
                        "stage" : "KEEP_MUTATIONS",
                        "nReturned" : 100,
                        "executionTimeMillisEstimate" : 40,
                        "works" : 10199,
                        "advanced" : 100,
                        "needTime" : 9900,
                        "needYield" : 198,
                        "saveState" : 199,
                        "restoreState" : 199,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "inputStage" : {
                                "stage" : "FETCH",
                                "filter" : {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                "nReturned" : 100,
                                "executionTimeMillisEstimate" : 40,
                                "works" : 10199,
                                "advanced" : 100,
                                "needTime" : 9900,
                                "needYield" : 198,
                                "saveState" : 199,
                                "restoreState" : 199,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "docsExamined" : 10000,
                                "alreadyHasObj" : 0,
                                "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "nReturned" : 10000,
                                        "executionTimeMillisEstimate" : 40,
                                        "works" : 10001,
                                        "advanced" : 10000,
                                        "needTime" : 0,
                                        "needYield" : 0,
                                        "saveState" : 199,
                                        "restoreState" : 199,
                                        "isEOF" : 1,
                                        "invalidates" : 0,
                                        "keyPattern" : {
                                                "b" : 1
                                        },
                                        "indexName" : "b_1",
                                        "isMultiKey" : false,
                                        "isUnique" : false,
                                        "isSparse" : false,
                                        "isPartial" : false,
                                        "indexVersion" : 1,
                                        "direction" : "forward",
                                        "indexBounds" : {
                                                "b" : [
                                                        "[55.0, 55.0]"
                                                ]
                                        },
                                        "keysExamined" : 10000,
                                        "dupsTested" : 0,
                                        "dupsDropped" : 0,
                                        "seenInvalidated" : 0
                                }
                        }
                }
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}
>

Now looking at the previos stats keys:
"winningPlan" shows it going to use the b index, with bound b:[55.0, 55.0]. It then going to pass that to up to FETCH stage of the query which fetches the final document, it going to look for the document a:17.


"executionTimeMillis" : 661
executionTime has increased. This query is slower than previous one.

"totalKeysExamined" : 10000,
"totalDocsExamined" : 10000,
We examinded 10000 documents and returned 10000 document and that's because the first stage of the document which is index scan of b returned 10000 document that has to be examined during the fetch stage.

This can be verified by inner most inputStage was the first stage run, that run query using index b and you can see it returned 10000 documents or we can see it returned pointer to 10000 document because index actually doesn't return 10000 documents.

Then in above inputStage we can see filter a:1 is applied on 10000 documents and they are whittle down to a final number of 100. "nReturned" : 100
And whenever you see number of documents examined much larger than the number of documents Returned, you know you did a lot of extra work that you look lot of extra data out of database and at some point it has to be inspected and then rejected before it returned to your actual client program. 

That's all what happen when you give the option "executionStats".


"allPlansExecution" verbosity mode of explain():

Let's first re-create the index:
> db.example.createIndex({a:1, b:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}

Creating new explainable object with allPlanExecution option.

> exp = db.example.explain("allPlansExecution")
Explainable(learn.example)

allPlansExecution:  allPlansExecution does what a query optimizer does periodicaly. It runs all possible indexes that can be used and it run it in parallel and then makes the decision about which one is fastest and it periodicaly does it. And when it remember which one is faster for certain shape of query and then always uses that index.

But when you run the explain command in allPlansExecution you are running the query optimizer that periodicaly run to determine what index would be used for any particular shape of the query.

> exp.find({a:17, b:55})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "learn.example",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "$and" : [
                                {
                                        "a" : {
                                                "$eq" : 17
                                        }
                                },
                                {
                                        "b" : {
                                                "$eq" : 55
                                        }
                                }
                        ]
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "a" : 1,
                                        "b" : 1
                                },
                                "indexName" : "a_1_b_1",
                                "isMultiKey" : false,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "a" : [
                                                "[17.0, 17.0]"
                                        ],
                                        "b" : [
                                                "[55.0, 55.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [
                        {
                                "stage" : "KEEP_MUTATIONS",
                                "inputStage" : {
                                        "stage" : "FETCH",
                                        "filter" : {
                                                "a" : {
                                                        "$eq" : 17
                                                }
                                        },
                                        "inputStage" : {
                                                "stage" : "IXSCAN",
                                                "keyPattern" : {
                                                        "b" : 1
                                                },
                                                "indexName" : "b_1",
                                                "isMultiKey" : false,
                                                "isUnique" : false,
                                                "isSparse" : false,
                                                "isPartial" : false,
                                                "indexVersion" : 1,
                                                "direction" : "forward",
                                                "indexBounds" : {
                                                        "b" : [
                                                                "[55.0, 55.0]"
                                                        ]
                                                }
                                        }
                                }
                        }
                ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 100,
                "executionTimeMillis" : 75,
                "totalKeysExamined" : 100,
                "totalDocsExamined" : 100,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 100,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 102,
                        "advanced" : 100,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 3,
                        "restoreState" : 3,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "docsExamined" : 100,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 100,
                                "executionTimeMillisEstimate" : 0,
                                "works" : 101,
                                "advanced" : 100,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 3,
                                "restoreState" : 3,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "keyPattern" : {
                                        "a" : 1,
                                        "b" : 1
                                },
                                "indexName" : "a_1_b_1",
                                "isMultiKey" : false,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "a" : [
                                                "[17.0, 17.0]"
                                        ],
                                        "b" : [
                                                "[55.0, 55.0]"
                                        ]
                                },
                                "keysExamined" : 100,
                                "dupsTested" : 0,
                                "dupsDropped" : 0,
                                "seenInvalidated" : 0
                        }
                },
                "allPlansExecution" : [
                        {
                                "nReturned" : 0,
                                "executionTimeMillisEstimate" : 30,
                                "totalKeysExamined" : 101,
                                "totalDocsExamined" : 101,
                                "executionStages" : {
                                        "stage" : "KEEP_MUTATIONS",
                                        "nReturned" : 0,
                                        "executionTimeMillisEstimate" : 30,
                                        "works" : 101,
                                        "advanced" : 0,
                                        "needTime" : 101,
                                        "needYield" : 0,
                                        "saveState" : 3,
                                        "restoreState" : 3,
                                        "isEOF" : 0,
                                        "invalidates" : 0,
                                        "inputStage" : {
                                                "stage" : "FETCH",
                                                "filter" : {
                                                        "a" : {
                                                                "$eq" : 17
                                                        }
                                                },
                                                "nReturned" : 0,
                                                "executionTimeMillisEstimate" : 30,
                                                "works" : 101,
                                                "advanced" : 0,
                                                "needTime" : 101,
                                                "needYield" : 0,
                                                "saveState" : 3,
                                                "restoreState" : 3,
                                                "isEOF" : 0,
                                                "invalidates" : 0,
                                                "docsExamined" : 101,
                                                "alreadyHasObj" : 0,
                                                "inputStage" : {
                                                        "stage" : "IXSCAN",
                                                        "nReturned" : 101,
                                                        "executionTimeMillisEstimate" : 3
                                                        "works" : 101,
                                                        "advanced" : 101,
                                                        "needTime" : 0,
                                                        "needYield" : 0,
                                                        "saveState" : 3,
                                                        "restoreState" : 3,
                                                        "isEOF" : 0,
                                                        "invalidates" : 0,
                                                        "keyPattern" : {
                                                                "b" : 1
                                                        },
                                                        "indexName" : "b_1",
                                                        "isMultiKey" : false,
                                                        "isUnique" : false,
                                                        "isSparse" : false,
                                                        "isPartial" : false,
                                                        "indexVersion" : 1,
                                                        "direction" : "forward",
                                                        "indexBounds" : {
                                                                "b" : [
                                                                        "[55.0, 55.0]"
                                                                ]
                                                        },
                                                        "keysExamined" : 101,
                                                        "dupsTested" : 0,
                                                        "dupsDropped" : 0,
                                                        "seenInvalidated" : 0
                                                }
                                        }
                                }
                        },
                        {
                                "nReturned" : 100,
                                "executionTimeMillisEstimate" : 0,
                                "totalKeysExamined" : 100,
                                "totalDocsExamined" : 100,
                                "executionStages" : {
                                        "stage" : "FETCH",
                                        "nReturned" : 100,
                                        "executionTimeMillisEstimate" : 0,
                                        "works" : 101,
                                        "advanced" : 100,
                                        "needTime" : 0,
                                        "needYield" : 0,
                                        "saveState" : 2,
                                        "restoreState" : 2,
                                        "isEOF" : 1,
                                        "invalidates" : 0,
                                        "docsExamined" : 100,
                                        "alreadyHasObj" : 0,
                                        "inputStage" : {
                                                "stage" : "IXSCAN",
                                                "nReturned" : 100,
                                                "executionTimeMillisEstimate" : 0,
                                                "works" : 101,
                                                "advanced" : 100,
                                                "needTime" : 0,
                                                "needYield" : 0,
                                                "saveState" : 2,
                                                "restoreState" : 2,
                                                "isEOF" : 1,
                                                "invalidates" : 0,
                                                "keyPattern" : {
                                                        "a" : 1,
                                                        "b" : 1
                                                },
                                                "indexName" : "a_1_b_1",
                                                "isMultiKey" : false,
                                                "isUnique" : false,
                                                "isSparse" : false,
                                                "isPartial" : false,
                                                "indexVersion" : 1,
                                                "direction" : "forward",
                                                "indexBounds" : {
                                                        "a" : [
                                                                "[17.0, 17.0]"
                                                        ],
                                                        "b" : [
                                                                "[55.0, 55.0]"
                                                        ]
                                                },
                                                "keysExamined" : 100,
                                                "dupsTested" : 0,
                                                "dupsDropped" : 0,
                                                "seenInvalidated" : 0
                                        }
                                }
                        }
                ]
        },
        "serverInfo" : {
                "host" : "himanshu-PC",
                "port" : 27017,
                "version" : "3.2.1",
                "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2"
        },
        "ok" : 1
}
>

We got lot more information. We have same executionStats as before. But we get a new thing: "allPlansExecution". This allPlansExecution is an array of different plans. The first one is actually rejected as its "nReturned" : 0 and the reason why its rejected is because database run the query using the b index and when it does that they examined 101 keys. We saw previously that when it uses b index and perform the query it examined 10000 documents and now it is examining 101 documents only. Why is that? 
The reason is that the 101 is as many as the database need to see to know this approach of using b index, is a looser. You can see it didn't return any document "nReturned" : 100 and documents examined "totalDocsExamined" : 101. And I have a plan which is the second plan in array of allPlansExecution, which is going to return 100 documents and only look at the 100 documents and that's using a_1_b_1 index.

Now you can actually see the logic the database applied to make the decision which is as soon as it saw that using the index just on b going to look at more documents than using the a_1_b_1 index, it immediately abandoned that path and didn't follow it through it's completion.

So although this executionPlanStats gives you some execution information about alternative paths satisfying this query, it won't tell you everything that would happen because it treats just like the query optimizer because when query optimizer know it's bad it stops. And if you remember when we removed a_1_b_1 index it uses b index and examined lot more documents (10000).

It good to have an index for every query, that is every query should hit an index but it also important that every index that is on your collection there will be atleast one query hitting it. Which is to say that when you have an index on a collection and it's never chosen, it never selected, it's just a waste and you are wasting time inserting into that index and keeping that index upto date when infact you don't need to be.

So you want to have a good balances between indexes on your collection and queries so that all the indexes get used and all the query can have atleast one index that can satisfy them and work efficiently.

24 comments:

  1. How to Solve if MongoDB not appropriately Working? Understand by means of MongoDB Technical Support
    At times when you are endeavoring to run your MongoDB, all of a sudden you get a blunder message. Clearly you don't comprehend why this really happens and to tackle this specific issue you simply erase everything with the goal that you can introduce everywhere. However, ensure on the off chance that you don't have a thought how to understand this specialized hiccups at that point rapidly connect with MongoDB Customer Support USA or Support for MongoDB Database Software. Get out first rate bolster with our specialized specialists and resolve your specific issue.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete
  2. Confronting Problem Installing MongoDB utilizing MacPorts? Contact to MongoDB Technical Support
    A large portion of the clients endeavoring to introduce MongoDB on Snow panther by utilizing MacPorts, however after at some point it stuck and nothing happened. Clients don't comprehend why this issue happens and what the most ideal approach to overcome of this issue is. Be that as it may, here we will let you know, with MongoDB Customer Support USA or MongoDB Online Support they can get top help with our expert specialists. Aside from this issue we convenient fix the bugs, recoup your information from misfortune and give moment fix to execution issues.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete
  3. Illuminate if Large Array Cause Performance Issue in MongoDB with MongoDB Technical Support
    At some point because of the reason of substantial exhibits your MongoDB Database stalls out and because of this reason you are not ready to play out your work with MongoDB. Ensure on the off chance that you need to streamline the execution of your MongoDB then you need to pick astutely a standout amongst the most trusted backings i.e. MongoDB Online Support or MongoDB Customer Support USA. Rapidly contact to our expert specialists and get the best arrangement and resolve your issues.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete
  4. How to Troubleshoot MongoDB Error Message? Contact to MongoDB Technical Support
    On the off chance that you are endeavoring to run MongoDB in your terminal then it gives you a blunder message. May be conceivable there is a linguistic structure mistake that is the reason you need to confront this issue. On the off chance that you have no clue how to manage this sentence structure blunder at that point rapidly attempt to contact MongoDB Online Support or MongoDB Customer Support USA. When you get associated with our specialized specialists, you will get Support for MongoDB Database Software and investigate your issues.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete
  5. How to light up if MongoDB shut down with Code 100? Contact to MongoDB Technical Support
    Exactly when your MongoDB shut down with the code 100 then it suggests something turning out gravely in your database that is the reason you have to stand up to this oversight. The principal respond in due order regarding this issue is it is conceivable that you keep running with physically like: you have to make a list for your DB data to be secured. Regardless, if not then another option is MongoDB Online Support or MongoDB Customer Support USA. We prescribe you to never pick any untouchable help for your MongoDB in light of the way that they charge exorbitantly. Regardless, here you will get most prominent help with the help of Support for MongoDB Database Software.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete
  6. How would I Repair My MongoDB Issue? Contact to MongoDB Online Support
    On the off chance that you recognize any sort of support in your MongoDB database, clearly it can be evidently difficult to supervise issue in light of the way that repairing MongoDB issue isn't a quick undertaking; it requires huge measures of incredible limits and strategy. In any case, here you have most clear opportunity to dispose of this issue i.e. MongoDB Technical Support or Support for MongoDB Database Software. We have immensity and ability to unravel any sort of database related issues genially.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Am really impressed about this blog because this blog is very easy to learn and understand clearly.This blog is very useful for the college students and researchers to take a good notes in good manner,I gained many unknown information.


    Data Science Training In Chennai

    Data Science Online Training In Chennai

    Data Science Training In Bangalore

    Data Science Training In Hyderabad

    Data Science Training In Coimbatore

    Data Science Training

    Data Science Online Training


    ReplyDelete
  9. Btreesystems Institute is rated as the No:1 Software Training Institute in Chennai with 100% placement assistance that consistently delivers quality training.aws training in chennai
    Python training in Chennai
    data science training in chennai
    hadoop training in chennai
    machine learning training chennai

    ReplyDelete
  10. Book Tenride call taxi in Chennai at most affordable taxi fare for Local or Outstation rides. Get multiple car options with our Chennai cab service
    chennai to kochi cab
    bangalore to kochi cab
    kochi to bangalore cab
    chennai to hyderabad cab
    hyderabad to chennai cab

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. This is the exact information I am been searching for, Thanks for sharing the required infos with the clear update and required points. To appreciate this I like to share some useful information

    Mongodb Training in Bangalore

    ReplyDelete
  13. ecommerce website design company
    ecommerce development solutions

    ReplyDelete

Mongodb explain() Query Analyzer and it's Verbosity

First creating 1 million documents: > for(i=0; i<100; i++) { for(j=0; j<100; j++) {x = []; for(k=0; k<100; k++) { x.push({a:...