Performance of count for mongodb
A count()
without a query predicate is a fast/estimated count read from the collection statistics, so should return in constant time regardless of the total number of documents. This is the same value returned by db.collection.stats().count
and the $collStats
aggregation stage (MongoDB 3.6+). Note: with the WiredTiger storage engine, collection statistics are persisted periodically and may not be accurate after unclean shutdown.
A count()
with query criteria will provide a more accurate result, but will need to iterate a suitable index (or perform a collection scan if there are no candidate indexes).
You can confirm the query planning outcome by reviewing the explain()
output for a count.
The winning plan for a fast count only has a COUNT
stage:
> db.zipcodes.explain().count().queryPlanner.winningPlan
{ "stage" : "COUNT" }
The winning plan for a count using an index will have a COUNT_SCAN
input stage:
> db.zipcodes.explain().count({city:'Sydney'}).queryPlanner.winningPlan
{
"stage" : "COUNT",
"inputStage" : {
"stage" : "COUNT_SCAN",
"keyPattern" : {
"city" : 1
},
"indexName" : "city_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"city" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"indexBounds" : {
"startKey" : {
"city" : "Sydney"
},
"startKeyInclusive" : true,
"endKey" : {
"city" : "Sydney"
},
"endKeyInclusive" : true
}
}
}
The winning plan for a count requiring a collection scan will have a COLLSCAN
input stage:
> db.zipcodes.explain().count({cityx:'Sydney'}).queryPlanner.winningPlan
{
"stage" : "COUNT",
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"cityx" : {
"$eq" : "Sydney"
}
},
"direction" : "forward"
}
}
The operation does not perform the query but instead counts the results that would be returned by the query. You can check this by looking into query plan for it using EXPLAIN
db.collection.explain("executionStats").count()