“Dashboard in the pilot's cockpit” by Mitchel Boot on Unsplash
Have you ever been asked — ‘Why is your MongoDB database server running slow?’. If you did wonder, ‘Which operations are making it slow?’ then you are thinking in right direction. This is one of the many articles in multi-part series, Mastering MongoDB — One tip a day, solely created for you to master MongoDB by learning ‘one tip a day’.
In a few series of articles, I would like to give various tips to help you answer the above question. This article discusses currentOp command — its applications, use case scenarios and finally use case scenarios and finally some hands-on lab exercises.
The currentOp is an administrative command that provides information about the current operations executing on the MongoDB server.
The currentOp must run against the admin database. When the authorization is turned on, the current user must either have ‘inprog’ privilege on admin database to view all operations or must use ‘$ownOps’ to view their own operations.
You could run the currentOp in mongo shell using either the adminCommand or the currentOp wrapper functions as show below.
db.adminCommand({"currentOp": 1})
// or
db.adminCommand({"currentOp": 1, "$ownOps" : true})
The MongoDB currentOp command via db.adminCommand
An alternative wrapper function for the above adminCommand
db.currentOp()
// or
db.currentOp({"$ownOps" : true})
The MongoDB currentOp command via a db.currentOp() wrapper function.
The use case for the currentOp command is to gathering information about operations currently executing on the MongoDB server. The currentOp command helps you find
The below example will help you find query operations using no index { “planSummary”: “COLLSCAN” }
db.adminCommand({
"currentOp": true,
"op" : "query",
"planSummary": "COLLSCAN"
})
The MongoDB currentOp command to help find queries not using any index
The below example will help you find all operations with numYields greater than or 100 on guidebook database. Notice that the regular expression “ns”: /^guidebook./ is also used to further filter the operations for guidebook database.
db.adminCommand({
"currentOp": true,
"ns": /^guidebook\./,
"numYields" : {"$gte": 100}
})
The MongoDB currentOp command to help you find database operations with number of yields greater than or equal to 100
The following example returns information on all the write operations that are waiting for a lock.
db.adminCommand({
"currentOp": true,
"waitingForLock" : true,
"$or": [
{ "op" : { "$in" : [ "insert", "update", "remove" ] } },
{ "query.findandmodify": { "$exists": true } }
]
})
The MongoDB currentOp command to help you find all the write operations that are waiting for a lock.
The following example returns information on all the operations running longer than 300 milliseconds.
db.adminCommand({
"currentOp": true,
"microsecs_running" : {"$gte" : 300000}
})
/*
// output for the above command
{
"inprog": [{
"host": "shyam-macbook.local:27017",
"desc": "conn",
"threadId": "0x70000a805000",
"connectionId": 3807,
"client": "127.0.0.1:52818",
"appName": "MongoDB Shell",
"clientMetadata": {
"application": {
"name": "MongoDB Shell"
},
"driver": {
"name": "MongoDB Internal Client",
"version": "3.6.2"
},
"os": {
"type": "Darwin",
"name": "Mac OS X",
"architecture": "x86_64",
"version": "17.5.0"
}
},
"active": true,
"currentOpTime": "2018-05-16T15:20:22.253-0500",
"opid": 835646,
"secs_running": NumberLong(0),
"microsecs_running": NumberLong(343179),
"op": "update",
"ns": "guidebook.restaurants",
"command": {
"q": {
},
"u": {
"$inc": {
"visitor_count": 1
}
},
"multi": true,
"upsert": false
},
"planSummary": "COLLSCAN",
"numYields": 400,
"locks": {
"Global": "w",
"Database": "w",
"Collection": "w"
},
"waitingForLock": false,
"lockStats": {
"Global": {
"acquireCount": {
"r": NumberLong(401),
"w": NumberLong(401)
}
},
"Database": {
"acquireCount": {
"w": NumberLong(401)
}
},
"Collection": {
"acquireCount": {
"w": NumberLong(401)
}
}
}
}],
"ok": 1
}
*/
The MongoDB currentOp command to help you find all the operations running longer than 300 milliseconds.
This lab exercise makes use of the restaurants sample dataset from MongoDB. Please follow the below instructions to import the restaurants data, generate some load to help you learn the concepts discussed in here.
#!/bin/sh
# download and import the restaurant sample data set
wget https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json
mongoimport --db guidebook --collection restaurants --type json --file ./primer-dataset.json
# download and run the load generation script
wget https://goo.gl/BXHH2d -O labs-performance-restaurant.js
mongo guidebook --eval "load('./labs-performance-restaurant.js');r.performReads();" > /dev/null 2>&1 &
# open mongo shell and practice all the above use cases for currentOp
mongo guidebook
A bash script to help you download, import and generate load on the sample restaurant database.
The db.currentOp() command provides means to find all the queries that are currently running on your MongoDB server. The optional fields can be further leveraged to help filter the results to specific criteria.
I want to reiterate a very important point — “the db.currentOp() returns the information on in-progress operations”.
If the queries of your interest execute very fast (a good thing), it may not even show up in currentOp output (most frustrating), if you ran the db.currentOp() command a tad bit early or late.
To ensure you capture all your operations over certain period of time, you may execute the db.currentOp() command in a while loop as shown below.
var i = 0;
while(i++<10) {
printjson(db.currentOp());
// sleep for 10 ms if required.
sleep(10)
}
A JavaScript function to execute currentOp in a while loop to capture operations over a period of time.
However, to capture operations over long period of time and consolidating the output for further processing would be become quite challenging. To help you properly capture all the queries over the period of time, you would need use Profiling. But that’s a topic for another day.
Hopefully, you learned something new today on you scale the path to “Mastering MongoDB — One tip a day”.