explain() method: MongoDB

We’ve seen the working of explain() method briefly in previous video tutorials – in this video tutorial lets dive in to learn more about this useful method, which helps us analyze and optimize our MongoDB commands.

explain-method-mongodb

Related Read:
Create and Insert Documents: MongoDB
index creation: MongoDB

temp: database name
name: collection name

Inserting 1000 Documents

1
2
3
4
5
6
7
8
MongoDB shell version: 2.6.1
connecting to: test
 
> use temp
switched to db temp
 
> for(i = 1; i < = 1000; i++) db.name.insert({a: i, b: i, c: i});
WriteResult({ "nInserted" : 1 })

Here we inserted 1000 documents using for loop.

Basic Cursor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> db.name.find({a: 5})
{ "_id" : ObjectId("53dcd070340ac74e061d7215"), "a" : 5, "b" : 5, "c" : 5 }
 
> db.name.find({a: 5}).explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1000,
        "nscanned" : 1000,
        "nscannedObjectsAllPlans" : 1000,
        "nscannedAllPlans" : 1000,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 7,
        "nChunkSkips" : 0,
        "millis" : 1,
        "server" : "Satish-PC:27017",
        "filterSet" : false
}

Here MongoDB server is returning a basic cursor, as we do not have index on field “a”. Also note that, it’s scanning 1000 documents in the “name” collection and scanning 1000 index keys in “system.indexes” collection, where the default key is “_id”.

explain() method: MongoDB


[youtube https://www.youtube.com/watch?v=q59nF4ziW-w]

YouTube Link: https://www.youtube.com/watch?v=q59nF4ziW-w [Watch the Video In Full Screen.]



Creating Index on fields “a” and “b”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
> db.name.ensureIndex({a: 1, b: 1});
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
 
> db.name.find({a: 5}).explain()
{
        "cursor" : "BtreeCursor a_1_b_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "a" : [
                        [
                                5,
                                5
                        ]
                ],
                "b" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ]
        },
        "server" : "Satish-PC:27017",
        "filterSet" : false
}

Here we create index on key “a” and “b” – it’s called compound key – after which the explain() method shows that MongoDB server is returning a Btree cursor, meaning it’s making use of index key to execute the query/command.

Also not the number of objects scanned in the “name” collection as well as in the “system.indexes” collection.

indexOnly: true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
> db.name.find({a: 5})
{ "_id" : ObjectId("53dcd070340ac74e061d7215"), "a" : 5, "b" : 5, "c" : 5 }
 
> db.name.find({a: 5}, {a: 1, b: 1, _id: 0})
{ "a" : 5, "b" : 5 }
 
> db.name.find({a: 5}, {a: 1, b: 1, _id: 0}).explain()
{
        "cursor" : "BtreeCursor a_1_b_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 0,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 0,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : true,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "a" : [
                        [
                                5,
                                5
                        ]
                ],
                "b" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ]
        },
        "server" : "Satish-PC:27017",
        "filterSet" : false
}

Covered Index or indexOnly
If our command is requesting for values present inside the index, mongo engine will fetch that information from the “system.indexes” collection itself and does not go to the collection where the entire document is present – in our case “name” collection. Since index is on keys “a” and “b” in our case, if we query for “a” and “b” values only, it fetches those values directly from the index information and will not go to “name” collection. Hence the speed of execution of the command is faster, and this type of commands are very efficient in creating optimized web applications.

Note from above explain() result, the number of objects scanned in the “name” collection is 0, and the number of scans made on indexes in only 1.