MongoDB execute query from a file and measure time - mongodb

I have a txt file with mongoDB queries, like this:
db.telephone.find({'brand' : 'Apple'});
db.telephone.find({'brand' : 'Samsung'});
...to a total of about 1500 rows. I am executing this query like this.
mongo myDatabase C:\path\mongoDB.txt
Now I need to measure the time how long it takes to execute all of these queries. I dont really care about the output, I really only care about the time it takes (as a part of an experiment).
I thought that if I create a collection times and insert current time to it like this db.times.insert({time: Date()}); at the beginning and end of the query file, it would do what I need, but it seemingly does not work, as both of these result times are the same in the end (and I believe that executing all these queries did take more than 1 second for sure).
Is this because I dont print the output, so the queries dont really get executed? Or why does this not work? And is there a better way how to measure the time it takes to execute these queries from a file? Thanks you.

You can assign start and end time in the file itself. The following is an example:
var start_time = new Date().valueOf();
db.telephone.find({'brand' : 'Apple'});
db.telephone.find({'brand' : 'Samsung'});
var end_time = new Date().valueOf();
print(end_time-start_time);
How we can precisely measure the execution time?
To analyze the query, we can use explain(). It returns the complete statistics of the query. The following is an example:
db.telephone.find({'brand' : 'Apple'}).explain("executionStats")
Output:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "check.telephone",
"indexFilterSet" : false,
"parsedQuery" : {
"brand" : {
"$eq" : "Apple"
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"brand" : {
"$eq" : "Apple"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 35,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"brand" : {
"$eq" : "Apple"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 3,
"advanced" : 1,
"needTime" : 1,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 1
}
},
"serverInfo" : {
"host" : "theMechanic",
"port" : 27017,
"version" : "4.0.11",
"gitVersion" : "417d1a712e9f040d54beca8e4943edce218e9a8c"
},
"ok" : 1
}
Note: The executionStats.executionTimeMillis holds actual query execution time.

Related

MongoDB disk read performance is very low

I have a MongoDB instance with a database and a collection with 80GB of data. The number of documents inside is about 4M with a comparatively large document size of about 20kB on average. Among other more elementary stuff, each documents contains one list of 1024 elements and also 3-4 lists of 200 numbers.
I perform a simple batch find query over a properly indexed string field ('isbn'), intending to get 5000 documents (projected on relevant part) in one batch. For this, I use the $in operator:
rows = COLLECTION.find({"isbn": {"$in": candidate_isbns}}, {"_id": 0,
"isbn": 1,
"other_stuff": 1})
The IXSCAN stage works properly as intended. Since the corresponding documents, however, are not within the WiredTiger cache yet (and probably never will be for my limited 32GB RAM), the data has to be read from disk during FETCH in most cases. (Unfortunately, "other_stuff" is too heavy to yield for an index that could cover this query.)
The SSD attached to my virtual cloud machine has a read performance of about 90MB/s, which is not great, but should be sufficient for now. However, when I monitor the disk read speed (via iostats, for example) the speed during the query goes down to roughly 3MB/s, which seems to be very poor. I can verify this poor behaviour by checking the profiler output (MongoDB seems to split the 5000 in further batches, so I show only the output for a sub-batch of 2094):
{
"op" : "getmore",
"ns" : "data.metadata",
"command" : {
"getMore" : NumberLong(7543502234201790529),
"collection" : "metadata",
"lsid" : {
"id" : UUID("2f410f2d-2f74-4d3a-9041-27c4ddc51bd2")
},
"$db" : "data"
},
"originatingCommand" : {
"$truncated" : "{ find: \"metadata\", filter: { isbn: { $in: [ \"9783927781313\", ..."
},
"cursorid" : NumberLong(7543502234201790529),
"keysExamined" : 4095,
"docsExamined" : 2095,
"numYield" : 803,
"nreturned" : 2094,
"locks" : {
"ReplicationStateTransition" : {
"acquireCount" : {
"w" : NumberLong(805)
}
},
"Global" : {
"acquireCount" : {
"r" : NumberLong(805)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(804)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(804)
}
},
"Mutex" : {
"acquireCount" : {
"r" : NumberLong(1)
}
}
},
"flowControl" : {},
"storage" : {
"data" : {
"bytesRead" : NumberLong(65454770),
"timeReadingMicros" : NumberLong(21386543)
}
},
"responseLength" : 16769511,
"protocol" : "op_msg",
"millis" : 21745,
"planSummary" : "IXSCAN { isbn: 1 }",
"execStats" : {
"stage" : "PROJECTION_SIMPLE",
"nReturned" : 2196,
"executionTimeMillisEstimate" : 21126,
"works" : 4288,
"advanced" : 2196,
"needTime" : 2092,
"needYield" : 0,
"saveState" : 817,
"restoreState" : 817,
"isEOF" : 0,
"transformBy" : {},
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 2196,
"executionTimeMillisEstimate" : 21116,
"works" : 4288,
"advanced" : 2196,
"needTime" : 2092,
"needYield" : 0,
"saveState" : 817,
"restoreState" : 817,
"isEOF" : 0,
"docsExamined" : 2196,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 2196,
"executionTimeMillisEstimate" : 531,
"works" : 4288,
"advanced" : 2196,
"needTime" : 2092,
"needYield" : 0,
"saveState" : 817,
"restoreState" : 817,
"isEOF" : 0,
"keyPattern" : {
"isbn" : 1.0
},
"indexName" : "isbn_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"isbn" : []
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"isbn" : [
"[\"9780230391451\", \"9780230391451\"]",
"[\"9780230593206\", \"9780230593206\"]",
... ]
},
"keysExamined" : 4288,
"seeks" : 2093,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
},
"ts" : ISODate("2022-01-24T07:57:12.132Z"),
"client" : "my_ip",
"allUsers" : [
{
"user" : "myUser",
"db" : "data"
}
],
"user" : "myUser#data"
}
By looking at the ratio of bytesRead vs. timeReadingMicros, this poor read speed of about 3MB/s can be confirmed, indeed.
My question: Why does this degradation of speed take place? Is it pathological, so that I need to do further investigations, or is it the expected behaviour, given the data setup above?
Any help is highly appreciated!

Why isn't MongoDB using my Text index?

I've got a Mongo collection with 1691721 items within it, containing essentially location information. I'm attempting to do a regex search into this, and it's pretty slow - but I don't understand why, as I thought I had appropriate indexes in place.
A typical document
{
"_id" : ObjectId("58c08029ef4468c8157455fa"),
"ng" : [
394235,
806529
],
"postcode" : "AB101AB"
}
Indexes
I've created a text index on the postcode field, which you can see here in the full list of indexes:
db.locations.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "Traders.locations"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "postcode_text",
"ns" : "Traders.locations",
"weights" : {
"postcode" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]
Query
At this point in time, all I care about is the postcode field. So I've tried writing a query to obtain the last value:
db.locations.find({ postcode: { $regex: /^ZE29XN$/ } }, { postcode: 1, _id: 0 })
Now this takes a while to run, roughly 700ms to be precise which is a lot longer than I was expecting. As far as I was concerned this is a covered query, I've got a text index on the single field I care about. However if I explain the above query it suggests it's using a COLLSCAN, but I don't understand why:
db.locations.find({ postcode: { $regex: /^ZE29XN$/ } }, { postcode: 1, _id: 0 }).explain("allPlansExecution")
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "Traders.locations",
"indexFilterSet" : false,
"parsedQuery" : {
"postcode" : {
"$regex" : "^ZE29XN$"
}
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"postcode" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"postcode" : {
"$regex" : "^ZE29XN$"
}
},
"direction" : "forward"
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 732,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1691721,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 1,
"executionTimeMillisEstimate" : 697,
"works" : 1691723,
"advanced" : 1,
"needTime" : 1691721,
"needYield" : 0,
"saveState" : 13223,
"restoreState" : 13223,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"postcode" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"postcode" : {
"$regex" : "^ZE29XN$"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 676,
"works" : 1691723,
"advanced" : 1,
"needTime" : 1691721,
"needYield" : 0,
"saveState" : 13223,
"restoreState" : 13223,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 1691721
}
},
"allPlansExecution" : [ ]
},
"serverInfo" : {
"host" : "DESKTOP",
"port" : 27017,
"version" : "3.4.2",
"gitVersion" : "3f76e40c105fc223b3e5aac3e20dcd026b83b38b"
},
"ok" : 1
}
My Question
Why is the text index I've created not being used, and ultimately how can I make my query faster?
I should note that I'm open to alternative to using the $regex however I do need to be able to allow for a "starts with" - so ZE.* or ZE2.* or ZE29XN should all be searchable at speed.
Something potentially useful to note, I wondered if when I eventually get my index working, that marking it as unique: true might help speed things up. However running it produced a duplicate key error (despite the fact I can't find one when I run an aggregation - can dig into this if need be, but I'm not sure it's related).
A quick summary of text search operators in MongoDB:
$regex: provides regular expression capabilities for pattern matching strings in queries. The $regex operator does support partial matches but it will only be index covered if the search string is anchored (i.e. uses a leading ^).
$text: performs a text search on the content of the fields indexed with a text index (use of the $text operator is a necessary precondition for MongoDB to use a text index). These searches are typically 'fast' (subjective term but when you have one working you'll see what that means) but they do not support partial matches so you won't be able to 'text search' for partial postcodes.
With that in mind it looks like you are attempting to use partial matching (via $regex) against a text index. This will not work because a text index is only engaged for the $text operator.
Your stated requirements are:
You want partial string matches
You want index coverage
You can meet these requirements by (1) using $regex and (2) indexing (a normal index not a text index) the postcode field. This is subject to one (important!) caveat: your search strings must be anchored. So this requirement: "need to be able to allow for a "starts with" - so ZE.* or ZE2.* or ZE29XN" should be fine. But a search such as: .*29XN will not be index covered.

MongoDB query taking too much time to retrieve data

I have one collection with 3 million documents and the following indexes:
{ ts : 1 } , {u_id: 1}
Note that these are two separate ascending indexes, not a compound index.
When I run this query:
db.collection.find({u_id: 'user'}).sort({ts : -1}).skip(0).limit(1)
it takes +100ms. I have the following logs:
2017-04-15T06:42:01.147+0000 I COMMAND [conn783] query
db.collection query: { orderby: { ts: -1 }, $query: {
u_id: "user-ki-id } } planSummary: IXSCAN { u_id:
1 }, IXSCAN { u_id: 1 } ntoreturn:1 ntoskip:0 keysExamined:10795
docsExamined:10795 hasSortStage:1 cursorExhausted:1 keyUpdates:0
writeConflicts:0 numYields:86 nreturned:1 reslen:771 locks:{ Global: {
acquireCount: { r: 174 } }, Database: { acquireCount: { r: 87 } },
Collection: { acquireCount: { r: 87 } } } 246ms
A few notable points about the problem:
There is no other load on MongoDB i.e. no other queries which take +100ms
This is happening every minute; I think I am storing data every minute so this is happening
The query flow is to first run the read query (as above), then the next query is a bulk insertion. This flow is repeated every one minute.
So my questions are:
Why is it happening? Are there any design flaws in my indexing?
Might it be worthwhile to change indexing to be descending, like {ts: -1}? What is the actual difference between these indexes?
According to MongoDB documentation, when you are doing sorting with order then result will pick from disk not "in-memory". Does this explain why it takes +100ms?
Can anybody explain me profiling log in detail level?
Is it desired behaviour of MongoDB?
The same thing is also happening when I run a range search on this collection; this takes 3-5 seconds.
EDIT:
I have only add {u_id: 1, ts: -1} index. Remove all other index (except _id). Still in first time query execution taking +100ms. This should not happen.
Query:
db.getCollection('locations') .find({u_id: "USR-WOWU"})
.sort({ts: -1}) .explain(true)
OutPut::
/* 1 */ {
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "db_name.collection_name",
"indexFilterSet" : false,
"parsedQuery" : {
"user_id" : {
"$eq" : "USR-WOWU"
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"u_id" : 1.0,
"ts" : -1.0
},
"indexName" : "u_id_1_ts_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"u_id" : [
"[\"USR-WOWU\", \"USR-WOWU\"]"
],
"ts" : [
"[MaxKey, MinKey]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 164,
"executionTimeMillis" : 119,
"totalKeysExamined" : 164,
"totalDocsExamined" : 164,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 164,
"executionTimeMillisEstimate" : 120,
"works" : 165,
"advanced" : 164,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 164,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 164,
"executionTimeMillisEstimate" : 0,
"works" : 165,
"advanced" : 164,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"u_id" : 1.0,
"ts" : -1.0
},
"indexName" : "u_id_1_ts_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"u_id" : [
"[\"USR-WOWU\", \"USR-WOWU\"]"
],
"ts" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 164,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
},
"allPlansExecution" : []
},
"serverInfo" : {
"host" : "manish",
"port" : 22022,
"version" : "3.2.13",
"gitVersion" : "23899209cad60aaafe114f6aea6cb83025ff51bc"
},
"ok" : 1.0 }
Please copy above jSON and format into any editor.
After above query, the next same query will response with in ~2 ms. But When I do few insertion then after one min same thing will be repeated. (1st time query will take time +100ms and then it will take ~2ms.)
Is something missing or anything is required to configuration in my mongoDB ??
Why is it happening
The docsExamined:10795 and hasSortStage:1 portions of this log line indicates that the query is scanning 10,795 from disk and then sorting the results in memory. A guide on interpreting log lines can be found here.
A performance improvement can likely be gained by indexing this query to avoid the in-memory sort.
For this query, you should try creating the index { 'u_id' : 1, 'ts' : -1 }.
Is it really worthfull if I will change indexing like {ts: -1} in descending order.
Indexes can be read in either direction, so the index order isn't super important on single field indexes. However, sort ordering can be very important in compound indexes.
Updated
Based on the explain plan, the query is now properly using the index to read the results from the index in order, which avoids the in-memory sort. It looks like this knocked off ~100ms off the query.
However, it looks like this query is no longer using .skip(0).limit(1). Can you add these back in and see if performance improves?
There doesn't appear to be anything wrong with your deployment; this behavior seems normal for queries that are not fully indexed.
Re-running the exact same query will be quick because the existing results ("the working set") are already stored in memory. Inserting new data can make the results of the query change, meaning the results may need to be read back into memory again.

MongoDB, can query fields slow down a query even if they form a partition?

Assuming I have only male and females in my user collection. Is the following :
User.find({ gender: { $in: ['male','female'] }})
slower than this one :
User.find()
I feel like it would be, but I don't really know how MongoDB works internally. Both requests return the entire collection. I'm building a filter feature and I'd like to simplify my api code by considering that every call is filtered somehow.
it is a good question as it touches basic query planning capabilites.
Comparing explain results we can see that using IN invokes collection scan by specified query parameter - which is more expensive than basic document dump, when querying without parameters.
db.User.find({ gender: { $in: ['male','female'] }}).explain("executionStats")
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.User",
"indexFilterSet" : false,
"parsedQuery" : {
"gender" : {
"$in" : [
"female",
"male"
]
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"gender" : {
"$in" : [
"female",
"male"
]
}
},
"direction" : "forward"
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 24,
"executionTimeMillis" : 0,
"totalKeysExamined" : 0,
"totalDocsExamined" : 24,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"gender" : {
"$in" : [
"female",
"male"
]
}
},
"nReturned" : 24,
"executionTimeMillisEstimate" : 0,
"works" : 26,
"advanced" : 24,
"needTime" : 1,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 24
}
},
"serverInfo" : {
"host" : "greg",
"port" : 27017,
"version" : "3.2.3",
"gitVersion" : "b326ba837cf6f49d65c2f85e1b70f6f31ece7937"
},
"ok" : 1
}
db.User.find().explain("executionStats")
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.User",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : []
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : []
},
"direction" : "forward"
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 24,
"executionTimeMillis" : 0,
"totalKeysExamined" : 0,
"totalDocsExamined" : 24,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : []
},
"nReturned" : 24,
"executionTimeMillisEstimate" : 0,
"works" : 26,
"advanced" : 24,
"needTime" : 1,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 24
}
},
"serverInfo" : {
"host" : "greg",
"port" : 27017,
"version" : "3.2.3",
"gitVersion" : "b326ba837cf6f49d65c2f85e1b70f6f31ece7937"
},
"ok" : 1
}
When querying without a condition, it return all the documents without checking. But if you and a condition. Simply it compile the condition into BSON and match with the data in the database, Which is slower. But if you create an index on gender. You can not see any difference in time (in both cases)

Not able to create covered query in MongoDB

I am facing problem to create covered query. I am using Mongo 3 latest version. Here is my sample data which I have inserted 10006 documents into MongoDB.
db.order.insert({ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 })
db.order.insert({ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 })
db.order.insert({ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 })
db.order.insert({ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 })
db.order.insert({ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 })
For Covered Query, All the fields in the query are part of an index so I have created index for status, ord_date, cust_id and amount fields like :
db.orders.createIndex({status: 1})
db.orders.createIndex({amount: 1})
db.orders.createIndex({ord_date: 1})
db.orders.createIndex({cust_id: 1})
I have executed following query.
db.orders.find(
{status : "A"},{ord_date : 1, cust_id : 1}
).sort({ amount: -1 }).explain()
But This explain query returns executionStats.totalDocsExamined = 200 instead of executionStats.totalDocsExamined = 0. means it is scan documents when I execute query. In Mongo 3, We can check index covered a query using executionStats.totalDocsExamined instead of indexOnly.
Can anyone please suggest me what I am doing wrong in covered query ?
Here is my output after index suggestion by Markus:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "local.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"status" : {
"$eq" : "A"
}
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"_id" : 1,
"ord_date" : 1,
"cust_id" : 1
},
"inputStage" : {
"stage" : "SORT",
"sortPattern" : {
"amount" : -1
},
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"status" : {
"$eq" : "A"
}
},
"direction" : "forward"
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 10004,
"executionTimeMillis" : 70,
"totalKeysExamined" : 0,
"totalDocsExamined" : 10018,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 10004,
"executionTimeMillisEstimate" : 70,
"works" : 20026,
"advanced" : 10004,
"needTime" : 10021,
"needFetch" : 0,
"saveState" : 157,
"restoreState" : 157,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"_id" : 1,
"ord_date" : 1,
"cust_id" : 1
},
"inputStage" : {
"stage" : "SORT",
"nReturned" : 10004,
"executionTimeMillisEstimate" : 70,
"works" : 20026,
"advanced" : 10004,
"needTime" : 10020,
"needFetch" : 0,
"saveState" : 157,
"restoreState" : 157,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"amount" : -1
},
"memUsage" : 960384,
"memLimit" : 33554432,
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"status" : {
"$eq" : "A"
}
},
"nReturned" : 10004,
"executionTimeMillisEstimate" : 10,
"works" : 10020,
"advanced" : 10004,
"needTime" : 15,
"needFetch" : 0,
"saveState" : 157,
"restoreState" : 157,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 10018
}
}
},
"allPlansExecution" : [ ]
},
"serverInfo" : {
"host" : "pcd32",
"port" : 27017,
"version" : "3.0.7",
"gitVersion" : "6ce7cbe8c6b899552dadd907604559806aa2esd5"
}
}
While there are index intersections in MongoDB, they can be quite tricky to utilize. However, sticking to a rule of thumb is a rather safe bet:
When creating queries MongoDB, assume that only one index can be used at a time
This is especially true for covered queries, as detailed in the docs:
An index covers a query when both of the following apply:
all the fields in the query are part of an index, and
all the fields returned in the results are in the same index.
Having a compound index doesn't have drawbacks, when carefully crafted, as queries using only parts of that index can use it, too.
So in order to make your query covered, you need to have all keys you want to return in your index. Since you did not limit the fields returned ("projection" in MongoDB terms), I assume you need the _id field to be returned as well. Furthermore, your index should reflect your sorting order. So your index should look like:
db.orders.createIndex({_id:1,status:1, ord_date:1,cust_id:1,amount:-1})
for your query. Order matters, so in order to make best use of the newly created index, other queries should adhere to the same order of fields.
If you also need the _id field, then the below compound index should give you a covered query:
db.order.createIndex({status:1, amount:-1, ord_date:1, cust_id :1, _id:1})
If you don't need the _id field then use _id : 0 in the find(), so that _id is not retrieved and you can remove it from the index as well.
Note that in a covered query, ordering of the fields as compared to the actual query being executed is important for the index to be used in the execution of the query.