How to improve mongo queries with multikey index in array - mongodb

I just found out that 1 of our queries is quite slow. We use a multikey index in an array and not sure how we can actually improve this query.
Our data structure:
account: [{
accountId:string,
service:string
}]
Index key is:
{"account.accountId":1, "account.service":1}
Here's my query:
db.model.find({"account.accountId":"12345", "account.service":"GameCenter"}).explain();
executionStats (1 million records)
"executionStats" : {
"nReturned" : 1,
"executionTimeMillis" : 325,
"totalKeysExamined" : 122744,
"totalDocsExamined" : 122743,
"executionStages" : {
"stage" : "SHARD_MERGE",
"nReturned" : 1,
"executionTimeMillis" : 325,
"totalKeysExamined" : 122744,
"totalDocsExamined" : 122743,
"totalChildMillis" : NumberLong(834),
"shards" : [
{
"shardName" : "rs1",
"executionSuccess" : true,
"executionStages" : {
"stage" : "SHARDING_FILTER",
"nReturned" : 0,
"executionTimeMillisEstimate" : 300,
"works" : 40999,
"advanced" : 0,
"needTime" : 40998,
"needYield" : 0,
"saveState" : 320,
"restoreState" : 320,
"isEOF" : 1,
"invalidates" : 0,
"chunkSkips" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"account.accountId" : {
"$eq" : "G:8183971619"
}
},
"nReturned" : 0,
"executionTimeMillisEstimate" : 300,
"works" : 40999,
"advanced" : 0,
"needTime" : 40998,
"needYield" : 0,
"saveState" : 320,
"restoreState" : 320,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 40998,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 40998,
"executionTimeMillisEstimate" : 30,
"works" : 40999,
"advanced" : 40998,
"needTime" : 0,
"needYield" : 0,
"saveState" : 320,
"restoreState" : 320,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"account.service" : 1,
"account.accountId" : 1
},
"indexName" : "account.service_1_account.accountId_1",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"account.service" : [
"[\"GameCenter\", \"GameCenter\"]"
],
"account.accountId" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 40998,
"dupsTested" : 40998,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
},
{
"shardName" : "rs2",
"executionSuccess" : true,
"executionStages" : {
"stage" : "SHARDING_FILTER",
"nReturned" : 1,
"executionTimeMillisEstimate" : 240,
"works" : 40612,
"advanced" : 1,
"needTime" : 40610,
"needYield" : 0,
"saveState" : 317,
"restoreState" : 317,
"isEOF" : 1,
"invalidates" : 0,
"chunkSkips" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"account.accountId" : {
"$eq" : "G:8183971619"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 230,
"works" : 40612,
"advanced" : 1,
"needTime" : 40610,
"needYield" : 0,
"saveState" : 317,
"restoreState" : 317,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 40610,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 40611,
"executionTimeMillisEstimate" : 70,
"works" : 40612,
"advanced" : 40611,
"needTime" : 0,
"needYield" : 0,
"saveState" : 317,
"restoreState" : 317,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"account.service" : 1,
"account.accountId" : 1
},
"indexName" : "account.service_1_account.accountId_1",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"account.service" : [
"[\"GameCenter\", \"GameCenter\"]"
],
"account.accountId" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 40611,
"dupsTested" : 40611,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
},
{
"shardName" : "rs3",
"executionSuccess" : true,
"executionStages" : {
"stage" : "SHARDING_FILTER",
"nReturned" : 0,
"executionTimeMillisEstimate" : 270,
"works" : 41136,
"advanced" : 0,
"needTime" : 41135,
"needYield" : 0,
"saveState" : 321,
"restoreState" : 321,
"isEOF" : 1,
"invalidates" : 0,
"chunkSkips" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"account.accountId" : {
"$eq" : "G:8183971619"
}
},
"nReturned" : 0,
"executionTimeMillisEstimate" : 270,
"works" : 41136,
"advanced" : 0,
"needTime" : 41135,
"needYield" : 0,
"saveState" : 321,
"restoreState" : 321,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 41135,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 41135,
"executionTimeMillisEstimate" : 90,
"works" : 41136,
"advanced" : 41135,
"needTime" : 0,
"needYield" : 0,
"saveState" : 321,
"restoreState" : 321,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"account.service" : 1,
"account.accountId" : 1
},
"indexName" : "account.service_1_account.accountId_1",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"account.service" : [
"[\"GameCenter\", \"GameCenter\"]"
],
"account.accountId" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 41135,
"dupsTested" : 41135,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
]
}
},
To summarise, the query do use the indexes but scan a lot of documents to get the results (122k / 1million). We couldn't use covered index as we need to return some other information too.
Also something werid: I'm querying for a unique accoundId, but my indexBounds for account.accountId is:
"account.accountId" : [
"[MinKey, MaxKey]"
]
Thank you for your help!
Mars

After reading the executionStatus carefully, the query is actually scanning all indexes since "accountId" indexBounds is [MinKey, MaxKey].
I'm able to resolve this issue with $elemMatch
db.model.find({
account:{
$elemMatch:{
accountId:"111",
service:"facebook"
}
}
})

Related

MongoDB sort and limit performance issue

I'm facing with a strange issue. The explain of the query shows usage of index with a fast execution time in all stages but the last stage of LIMIT breaks it all. I have execution time of 60s and more!
The DB is used for marketing tool and we collect data on the campaign activity. We have 100k+ records in DB per each hour and I want to select all the 100k in batches of 5k (I tried to reduce it to 1k also) in order to make statistics aggregation.
Just for tests, I will add an example of the query explanation.
If I reduce the created_at date range to 10 minutes and I set the limit to 1000, it works fast.
If I set the created_at date range to 30 minutes and I set the limit to 1000, it stock again.
I have 8 CPU and 64 memory
Storage is with 6000 IOPS
The table include 900 million records in total
I have the following indexes:
created_at: 1
_id: 1
{created_at: 1, _id: 1} - not used in query
Slow query for 30 minutes
> db.logs.explain('allPlansExecution').aggregate([{"$match":{"created_at":{"$gte":ISODate('2021-06-02T20:00:00.000+00:00'),"$lte":ISODate('2021-06-02T20:30:00.000+00:00')}}},{"$sort":{"_id":1}},{"$limit":1000}], { allowDiskUse: true });
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "webpush.campaign_action_logs",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"created_at" : {
"$lte" : ISODate("2021-06-02T20:30:00Z")
}
},
{
"created_at" : {
"$gte" : ISODate("2021-06-02T20:00:00Z")
}
}
]
},
"optimizedPipeline" : true,
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"_id" : 1
},
"memLimit" : 104857600,
"limitAmount" : 100,
"type" : "simple",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"created_at" : 1
},
"indexName" : "created_at_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[new Date(1622664000000), new Date(1622665800000)]"
]
}
}
}
},
"rejectedPlans" : [
{
"stage" : "LIMIT",
"limitAmount" : 100,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"created_at" : {
"$lte" : ISODate("2021-06-02T20:30:00Z")
}
},
{
"created_at" : {
"$gte" : ISODate("2021-06-02T20:00:00Z")
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_id" : [
"[MinKey, MaxKey]"
]
}
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 100,
"executionTimeMillis" : 183411,
"totalKeysExamined" : 257959,
"totalDocsExamined" : 257959,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 100,
"executionTimeMillisEstimate" : 625,
"works" : 258061,
"advanced" : 100,
"needTime" : 257960,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 1,
"sortPattern" : {
"_id" : 1
},
"memLimit" : 104857600,
"limitAmount" : 100,
"type" : "simple",
"totalDataSizeSorted" : 187871472,
"usedDisk" : false,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 257959,
"executionTimeMillisEstimate" : 533,
"works" : 257960,
"advanced" : 257959,
"needTime" : 0,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 1,
"docsExamined" : 257959,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 257959,
"executionTimeMillisEstimate" : 265,
"works" : 257960,
"advanced" : 257959,
"needTime" : 0,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 1,
"keyPattern" : {
"created_at" : 1
},
"indexName" : "created_at_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[new Date(1622664000000), new Date(1622665800000)]"
]
},
"keysExamined" : 257959,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
},
"allPlansExecution" : [
{
"nReturned" : 100,
"executionTimeMillisEstimate" : 625,
"totalKeysExamined" : 257959,
"totalDocsExamined" : 257959,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 100,
"executionTimeMillisEstimate" : 625,
"works" : 258060,
"advanced" : 100,
"needTime" : 257960,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 0,
"sortPattern" : {
"_id" : 1
},
"memLimit" : 104857600,
"limitAmount" : 100,
"type" : "simple",
"totalDataSizeSorted" : 187871472,
"usedDisk" : false,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 257959,
"executionTimeMillisEstimate" : 533,
"works" : 257960,
"advanced" : 257959,
"needTime" : 0,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 1,
"docsExamined" : 257959,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 257959,
"executionTimeMillisEstimate" : 265,
"works" : 257960,
"advanced" : 257959,
"needTime" : 0,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 1,
"keyPattern" : {
"created_at" : 1
},
"indexName" : "created_at_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[new Date(1622664000000), new Date(1622665800000)]"
]
},
"keysExamined" : 257959,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
}
},
{
"nReturned" : 70,
"executionTimeMillisEstimate" : 178092,
"totalKeysExamined" : 258060,
"totalDocsExamined" : 258060,
"executionStages" : {
"stage" : "LIMIT",
"nReturned" : 70,
"executionTimeMillisEstimate" : 178092,
"works" : 258060,
"advanced" : 70,
"needTime" : 257990,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 0,
"limitAmount" : 100,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"created_at" : {
"$lte" : ISODate("2021-06-02T20:30:00Z")
}
},
{
"created_at" : {
"$gte" : ISODate("2021-06-02T20:00:00Z")
}
}
]
},
"nReturned" : 70,
"executionTimeMillisEstimate" : 178057,
"works" : 258060,
"advanced" : 70,
"needTime" : 257990,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 0,
"docsExamined" : 258060,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 258060,
"executionTimeMillisEstimate" : 645,
"works" : 258060,
"advanced" : 258060,
"needTime" : 0,
"needYield" : 0,
"saveState" : 9571,
"restoreState" : 9571,
"isEOF" : 0,
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_id" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 258060,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
}
}
]
},
"serverInfo" : {
"host" : "ip-10-0-3-171",
"port" : 27017,
"version" : "4.4.6",
"gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"
},
"ok" : 1
}
Faster query for 10 minutes:
> db.logs.explain('allPlansExecution').aggregate([{"$match":{"created_at":{"$gte":ISODate('2021-06-02T20:00:00.000+00:00'),"$lte":ISODate('2021-06-02T20:10:00.000+00:00')}}},{"$sort":{"_id":1}},{"$limit":1000}], { allowDiskUse: true });
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "webpush.campaign_action_logs",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"created_at" : {
"$lte" : ISODate("2021-06-02T20:10:00Z")
}
},
{
"created_at" : {
"$gte" : ISODate("2021-06-02T20:00:00Z")
}
}
]
},
"optimizedPipeline" : true,
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"_id" : 1
},
"memLimit" : 104857600,
"limitAmount" : 1000,
"type" : "simple",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"created_at" : 1
},
"indexName" : "created_at_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[new Date(1622664000000), new Date(1622664600000)]"
]
}
}
}
},
"rejectedPlans" : [
{
"stage" : "LIMIT",
"limitAmount" : 1000,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"created_at" : {
"$lte" : ISODate("2021-06-02T20:10:00Z")
}
},
{
"created_at" : {
"$gte" : ISODate("2021-06-02T20:00:00Z")
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_id" : [
"[MinKey, MaxKey]"
]
}
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1000,
"executionTimeMillis" : 1502,
"totalKeysExamined" : 58027,
"totalDocsExamined" : 58027,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 1000,
"executionTimeMillisEstimate" : 122,
"works" : 59029,
"advanced" : 1000,
"needTime" : 58028,
"needYield" : 0,
"saveState" : 122,
"restoreState" : 122,
"isEOF" : 1,
"sortPattern" : {
"_id" : 1
},
"memLimit" : 104857600,
"limitAmount" : 1000,
"type" : "simple",
"totalDataSizeSorted" : 42213931,
"usedDisk" : false,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 58027,
"executionTimeMillisEstimate" : 96,
"works" : 58028,
"advanced" : 58027,
"needTime" : 0,
"needYield" : 0,
"saveState" : 122,
"restoreState" : 122,
"isEOF" : 1,
"docsExamined" : 58027,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 58027,
"executionTimeMillisEstimate" : 40,
"works" : 58028,
"advanced" : 58027,
"needTime" : 0,
"needYield" : 0,
"saveState" : 122,
"restoreState" : 122,
"isEOF" : 1,
"keyPattern" : {
"created_at" : 1
},
"indexName" : "created_at_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[new Date(1622664000000), new Date(1622664600000)]"
]
},
"keysExamined" : 58027,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
},
"allPlansExecution" : [
{
"nReturned" : 101,
"executionTimeMillisEstimate" : 122,
"totalKeysExamined" : 58027,
"totalDocsExamined" : 58027,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 101,
"executionTimeMillisEstimate" : 122,
"works" : 58129,
"advanced" : 101,
"needTime" : 58028,
"needYield" : 0,
"saveState" : 121,
"restoreState" : 121,
"isEOF" : 0,
"sortPattern" : {
"_id" : 1
},
"memLimit" : 104857600,
"limitAmount" : 1000,
"type" : "simple",
"totalDataSizeSorted" : 42213931,
"usedDisk" : false,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 58027,
"executionTimeMillisEstimate" : 96,
"works" : 58028,
"advanced" : 58027,
"needTime" : 0,
"needYield" : 0,
"saveState" : 121,
"restoreState" : 121,
"isEOF" : 1,
"docsExamined" : 58027,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 58027,
"executionTimeMillisEstimate" : 40,
"works" : 58028,
"advanced" : 58027,
"needTime" : 0,
"needYield" : 0,
"saveState" : 121,
"restoreState" : 121,
"isEOF" : 1,
"keyPattern" : {
"created_at" : 1
},
"indexName" : "created_at_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[new Date(1622664000000), new Date(1622664600000)]"
]
},
"keysExamined" : 58027,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
}
},
{
"nReturned" : 3,
"executionTimeMillisEstimate" : 935,
"totalKeysExamined" : 58129,
"totalDocsExamined" : 58129,
"executionStages" : {
"stage" : "LIMIT",
"nReturned" : 3,
"executionTimeMillisEstimate" : 935,
"works" : 58129,
"advanced" : 3,
"needTime" : 58126,
"needYield" : 0,
"saveState" : 122,
"restoreState" : 122,
"isEOF" : 0,
"limitAmount" : 1000,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"created_at" : {
"$lte" : ISODate("2021-06-02T20:10:00Z")
}
},
{
"created_at" : {
"$gte" : ISODate("2021-06-02T20:00:00Z")
}
}
]
},
"nReturned" : 3,
"executionTimeMillisEstimate" : 935,
"works" : 58129,
"advanced" : 3,
"needTime" : 58126,
"needYield" : 0,
"saveState" : 122,
"restoreState" : 122,
"isEOF" : 0,
"docsExamined" : 58129,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 58129,
"executionTimeMillisEstimate" : 17,
"works" : 58129,
"advanced" : 58129,
"needTime" : 0,
"needYield" : 0,
"saveState" : 122,
"restoreState" : 122,
"isEOF" : 0,
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_id" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 58129,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
}
}
]
},
"serverInfo" : {
"host" : "ip-10-0-3-171",
"port" : 27017,
"version" : "4.4.6",
"gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"
},
"ok" : 1
}
Questions:
If the issue is the amount of doc scanned and we used index, how can I solve it? I do not think that looping over 5000k results in a sort order in a 300k docs should cuz an issue but maybe I'm wrong.
Why the LIMIT stage (with another stage of FETCH) causing the issue?
Thank you very much for all experts in advance!
The issue is the sort. Because you are using skip/limit on a sorted set, it must load the entire set from disk, then sort it in memory (possibly spilling to disk) in order to apply the skip/limit.
This means that if you have 100k documents matching the time range, you load all 100k to get the first batch, and then load 100k again to get the second batch.
An index in mongodb can support a sort if the index includes the field that is sorted on, and any fields that precede that key in the index creation spec are matched with an equality predicate.
Fields matched with inequality or ranges can be listed after the sort key.
The existing index on { _id:1 } is inefficient because it is non-selective and therefore requires reading the entire collection from diks.
The index on { created_at:1 } requires loading only those document that match the query, but they must then be sorted in memory.
To support this query, create an index on { _id:1, created_at:1 }. This index should significantly improve the performance because it can both eliminate the in-memory sort, and only require the query executor to load from disk those documents that match the query. This also has the benefit that the query executor can terminate as soon as the limit is satisfied.

What is needTime on MongoDB cursor.explain("executionStats")?

I was checking that my query is optimum or not. For that I used Cursor.explain("executionStats"). At there few keys present which I am curious to know about.
So I found needTime. I researched on MongoDB Official Documentation but unfortunately, I was not able to understand. Is there anyone who help me out regarding this.
This is my result:
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"views" : 0,
},
"inputStage" : {
"stage" : "SORT",
"sortPattern" : {
"createdate" : -1
},
"limitAmount" : 20,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"post_status" : {
"$eq" : 1
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"user_id" : 1,
"lastmodified" : -1
},
"indexName" : "user_id_1_lastmodified_-1",
"isMultiKey" : true,
"multiKeyPaths" : {
"user_id" : [ ],
"lastmodified" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"user_id" : [
"[MinKey, MaxKey]"
],
"lastmodified" : [
"[MaxKey, MinKey]"
]
}
}
}
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 20,
"executionTimeMillis" : 1,
"totalKeysExamined" : 386,
"totalDocsExamined" : 375,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 20,
"executionTimeMillisEstimate" : 0,
"works" : 409,
"advanced" : 20,
"needTime" : 388,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"views" : 0,
},
"inputStage" : {
"stage" : "SORT",
"nReturned" : 20,
"executionTimeMillisEstimate" : 0,
"works" : 409,
"advanced" : 20,
"needTime" : 388,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"createdate" : -1
},
"memUsage" : 19348,
"memLimit" : 33554432,
"limitAmount" : 20,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"nReturned" : 225,
"executionTimeMillisEstimate" : 0,
"works" : 388,
"advanced" : 225,
"needTime" : 162,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"post_status" : {
"$eq" : 1
}
},
"nReturned" : 225,
"executionTimeMillisEstimate" : 0,
"works" : 387,
"advanced" : 225,
"needTime" : 161,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 375,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 375,
"executionTimeMillisEstimate" : 0,
"works" : 387,
"advanced" : 375,
"needTime" : 11,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"user_id" : 1,
"lastmodified" : -1
},
"indexName" : "user_id_1_lastmodified_-1",
"isMultiKey" : true,
"multiKeyPaths" : {
"user_id" : [ ],
"lastmodified" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"user_id" : [
"[MinKey, MaxKey]"
],
"lastmodified" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 386,
"seeks" : 1,
"dupsTested" : 386,
"dupsDropped" : 11,
"seenInvalidated" : 0
}
}
}
}
}
},

MongoDB uses wrong index, even after clearing the query plan cache

I have the following command:
db.mycol.find({sourceId:ObjectId("596bac5a6f473e1a042bFFFF"),myFlag:false}).count()
It was taking a lot of time.
So I decided to add an index { "sourceId" : -1, "myFlag" : -1 }
MongoDB still kept taking the same time.
When I ran explain() on the find command, I noticed that mongoDB still kept using my old indexes.
db.mycol.find({sourceId:ObjectId("596bac5a6f473e1a042bFFFF"),myFlag:false}).explain(true)
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "mydb.mycol",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"sourceId" : {
"$eq" : ObjectId("596bac5a6f473e1a042bFFFF")
}
},
{
"myFlag" : {
"$eq" : false
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"sourceId" : 1
},
"indexName" : "sourceId_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "FETCH",
"filter" : {
"sourceId" : {
"$eq" : ObjectId("596bac5a6f473e1a042bFFFF")
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"myFlag" : -1
},
"indexName" : "myFlag_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"myFlag" : [
"[false, false]"
]
}
}
},
{
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"sourceId" : -1,
"timestamp" : -1
},
"indexName" : "sourceId_-1_timestamp_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
],
"timestamp" : [
"[MaxKey, MinKey]"
]
}
}
},
{
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"sourceId" : -1,
"timestamp" : 1
},
"indexName" : "sourceId_-1_timestamp_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
],
"timestamp" : [
"[MinKey, MaxKey]"
]
}
}
},
{
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"sourceId" : -1,
"myFlag" : -1
},
"indexName" : "sourceId_-1_myFlag_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
],
"myFlag" : [
"[false, false]"
]
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 2074,
"executionTimeMillis" : 33936,
"totalKeysExamined" : 2074,
"totalDocsExamined" : 2074,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"nReturned" : 2074,
"executionTimeMillisEstimate" : 31710,
"works" : 2075,
"advanced" : 2074,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 2074,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 2074,
"executionTimeMillisEstimate" : 0,
"works" : 2075,
"advanced" : 2074,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"sourceId" : 1
},
"indexName" : "sourceId_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
]
},
"keysExamined" : 2074,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
},
"allPlansExecution" : [
{
"nReturned" : 0,
"executionTimeMillisEstimate" : 1630,
"totalKeysExamined" : 101,
"totalDocsExamined" : 101,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"sourceId" : {
"$eq" : ObjectId("596bac5a6f473e1a042bFFFF")
}
},
"nReturned" : 0,
"executionTimeMillisEstimate" : 1630,
"works" : 101,
"advanced" : 0,
"needTime" : 101,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 101,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"myFlag" : -1
},
"indexName" : "myFlag_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"myFlag" : [
"[false, false]"
]
},
"keysExamined" : 101,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
{
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"totalKeysExamined" : 101,
"totalDocsExamined" : 101,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 101,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"sourceId" : -1,
"timestamp" : -1
},
"indexName" : "sourceId_-1_timestamp_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
],
"timestamp" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 101,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
{
"nReturned" : 101,
"executionTimeMillisEstimate" : 10,
"totalKeysExamined" : 101,
"totalDocsExamined" : 101,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"nReturned" : 101,
"executionTimeMillisEstimate" : 10,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 101,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"sourceId" : -1,
"timestamp" : 1
},
"indexName" : "sourceId_-1_timestamp_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
],
"timestamp" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 101,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
{
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"totalKeysExamined" : 101,
"totalDocsExamined" : 101,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 101,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 1554,
"restoreState" : 1554,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"sourceId" : -1,
"myFlag" : -1
},
"indexName" : "sourceId_-1_myFlag_-1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
],
"myFlag" : [
"[false, false]"
]
},
"keysExamined" : 101,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
{
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"totalKeysExamined" : 101,
"totalDocsExamined" : 101,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"myFlag" : {
"$eq" : false
}
},
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 88,
"restoreState" : 88,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 101,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 101,
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 88,
"restoreState" : 88,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"sourceId" : 1
},
"indexName" : "sourceId_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"sourceId" : [
"[ObjectId('596bac5a6f473e1a042bFFFF'), ObjectId('596bac5a6f473e1a042bFFFF')]"
]
},
"keysExamined" : 101,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
]
},
"serverInfo" : {
"host" : "gdm3d",
"port" : 27017,
"version" : "3.2.15",
"gitVersion" : "e11e3c1b9c9ce3f7b4a79493e16f5e4504e01140"
},
"ok" : 1
}
For some reason, it rejects the plan to use sourceId_-1_myFlag_-1 and goes with sourceId_1 and then filters myFlag document by document.
When I forced it to use the index, it returned the result immediately!
db.mycol.find({sourceId:ObjectId("596bac5a6f473e1a042bFFFF"),myFlag:false}).hint("sourceId_-1_myFlag_-1").count()
I read that periodically mongoDB runs all the plans and checks which one is faster, then uses that one in future.
I even tried restarting the mongodb, clearing query plan cache, restarting the computer. For some sourceIds with very less data, it did use the correct index automatically (I checked the index usage) but then it again started using the old ones.
I don't want to force it to use the index. How do I make sure it automatically does that?
Update:
It started using the correct one after some time. Atleast thats what the indexStats says.
However, the command still takes time, and when i give it hint, it gives output immediately.

mongodb text index not working

mongo3.4.6
hi export, I am new to mongodb, and I have some problem with indexing. below I create a text index on RequestId(string) inside recordInfo collection:
db.getCollection("RecordInfo").createIndex({"RequestId":"text"})
but when I try to query below:
db.getCollection("RecordInfo").find({"RequestId":"4513456313212313212aaaa"}).explain("executionStats"), you can see it's not using index:
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 17,
"totalKeysExamined" : 0,
"totalDocsExamined" : 9998,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"RequestId" : {
"$eq" : "4513456313212313212aaaa"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 21,
"works" : 10000,
"advanced" : 1,
"needTime" : 9998,
"needYield" : 0,
"saveState" : 78,
"restoreState" : 78,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 9998
}
},
then I try below with $text:
db.getCollection("RecordInfo").find({$text:{$search:"4513456313212313212aaaa"}}).explain("executionStats")
it gives me below,which I think pretty good one:
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 1,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "TEXT",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 5,
"advanced" : 1,
"needTime" : 3,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"indexPrefix" : {
},
"indexName" : "RequestId_text",
"parsedTextQuery" : {
"terms" : [
"4513456313212313212aaaa"
],
"negatedTerms" : [ ],
"phrases" : [ ],
"negatedPhrases" : [ ]
},
"textIndexVersion" : 3,
"inputStage" : {
"stage" : "TEXT_MATCH",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 5,
"advanced" : 1,
"needTime" : 3,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsRejected" : 0,
"inputStage" : {
"stage" : "TEXT_OR",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 5,
"advanced" : 1,
"needTime" : 3,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 1,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"_fts" : "text",
"_ftsx" : 1
},
"indexName" : "RequestId_text",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
},
"keysExamined" : 1,
"seeks" : 1,
"dupsTested" : 1,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
but why mongo don't use a index by default, so I use hint to force a index query with below:
db.getCollection("RecordInfo").find({"RequestId":"4513456313212313212aaaa"}).hint("RequestId_text").explain("executionStats"), it give me these, which it's not that good:
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 93,
"totalKeysExamined" : 49378,
"totalDocsExamined" : 9998,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"RequestId" : {
"$eq" : "4513456313212313212aaaa"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 91,
"works" : 49379,
"advanced" : 1,
"needTime" : 49377,
"needYield" : 0,
"saveState" : 386,
"restoreState" : 386,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 9998,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 9998,
"executionTimeMillisEstimate" : 50,
"works" : 49379,
"advanced" : 9998,
"needTime" : 39380,
"needYield" : 0,
"saveState" : 386,
"restoreState" : 386,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"_fts" : "text",
"_ftsx" : 1
},
"indexName" : "RequestId_text",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_fts" : [
"[MinKey, MaxKey]"
],
"_ftsx" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 49378,
"seeks" : 1,
"dupsTested" : 49378,
"dupsDropped" : 39380,
"seenInvalidated" : 0
}
}
},
To summaize, I want to use index or whatever method to query RequestId field which is string column fast. but if I force to use index, it seems not work for me only make my query worse. but if I use index another way, like below, I can see a pretty good query. but I can't specify on wich field I want to query this way.
db.getCollection("RecordInfo").find({$text:{$search:"4513456313212313212aaaa"}}).explain("executionStats")
Text search only works using the $text query operator.
When you execute db.getCollection("RecordInfo").find({"RequestId":"4513456313212313212aaaa"}), you're running a query for an exact match on that field.
From the question, it seems what you're looking for is a regular index, which you can create using db.getCollection("RecordInfo").createIndex({"RequestId": 1})
This will make your query using $text fail (because there is no text index) but will make the regular one use the index and avoid COLLSCAN.

Similar queries to different collections have vastly different performance

This query takes 66 seconds:
{
"op" : "query",
"ns" : "pipelines_odd.CachedUrl_319",
"query" : {
"find" : "CachedUrl_319",
"filter" : {
"$and" : [
{
"updated_at" : {
"$lt" : ISODate("2016-03-23T19:26:36.207Z")
}
},
{
"host_pattern_id" : 1844
}
]
},
"ntoreturn" : 100,
"sort" : {
"updated_at" : 1
}
},
"keysExamined" : 0,
"docsExamined" : 0,
"hasSortStage" : true,
"cursorExhausted" : true,
"keyUpdates" : 0,
"writeConflicts" : 0,
"numYield" : 18150,
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(36302)
},
"acquireWaitCount" : {
"r" : NumberLong(3078)
},
"timeAcquiringMicros" : {
"r" : NumberLong(3054408)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(18151)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(18151)
}
}
},
"nreturned" : 0,
"responseLength" : 20,
"millis" : 66576,
"execStats" : {
"stage" : "ENSURE_SORTED",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 6,
"advanced" : 0,
"needTime" : 5,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"nDropped" : 0,
"inputStage" : {
"stage" : "OR",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 6,
"advanced" : 0,
"needTime" : 5,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"locsForgotten" : 0,
"inputStages" : [
{
"stage" : "SORT",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 3,
"advanced" : 0,
"needTime" : 2,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"updated_at" : 1
},
"memUsage" : 0,
"memLimit" : 33554432,
"limitAmount" : 100,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 0,
"needTime" : 1,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"updated_at" : {
"$lt" : ISODate("2016-03-23T19:26:36.207Z")
}
},
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 0,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"host_pattern_id" : 1
},
"indexName" : "host_pattern_id_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"host_pattern_id" : [
"[1844, 1844]"
]
},
"keysExamined" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
},
{
"stage" : "SORT",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 3,
"advanced" : 0,
"needTime" : 2,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"updated_at" : 1
},
"memUsage" : 0,
"memLimit" : 33554432,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 0,
"needTime" : 1,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"updated_at" : {
"$lt" : ISODate("2016-03-23T19:26:36.207Z")
}
},
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 0,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"host_pattern_id" : 1
},
"indexName" : "host_pattern_id_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"host_pattern_id" : [
"[1844, 1844]"
]
},
"keysExamined" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
]
}
},
"ts" : ISODate("2016-03-30T19:27:56.347Z"),
"allUsers" : [ ],
"user" : ""
}
While a similar query against a different collection of about the same size runs in 10 milliseconds:
{
"op" : "query",
"ns" : "pipelines_odd.CachedUrl_257",
"query" : {
"find" : "CachedUrl_257",
"filter" : {
"$or" : [
{
"$and" : [
{
"updated_at" : {
"$lt" : ISODate("2016-01-23T20:55:52.174Z")
}
},
{
"host_pattern_id" : 5046
}
]
}
]
},
"ntoreturn" : 100,
"sort" : {
"updated_at" : 1
}
},
"cursorid" : NumberLong("16448827549027"),
"keysExamined" : 100,
"docsExamined" : 100,
"keyUpdates" : 0,
"writeConflicts" : 0,
"numYield" : 1,
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(4)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(2)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(2)
}
}
},
"nreturned" : 100,
"responseLength" : 42183,
"millis" : 10,
"execStats" : {
"stage" : "CACHED_PLAN",
"nReturned" : 100,
"executionTimeMillisEstimate" : 10,
"works" : 100,
"advanced" : 100,
"needTime" : 0,
"needYield" : 0,
"saveState" : 2,
"restoreState" : 1,
"isEOF" : 0,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"host_pattern_id" : {
"$eq" : 5046
}
},
"nReturned" : 100,
"executionTimeMillisEstimate" : 10,
"works" : 100,
"advanced" : 100,
"needTime" : 0,
"needYield" : 0,
"saveState" : 2,
"restoreState" : 1,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 100,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 100,
"executionTimeMillisEstimate" : 0,
"works" : 100,
"advanced" : 100,
"needTime" : 0,
"needYield" : 0,
"saveState" : 2,
"restoreState" : 1,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"updated_at" : 1
},
"indexName" : "updated_at_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"updated_at" : [
"(true, new Date(1453582552174))"
]
},
"keysExamined" : 100,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"ts" : ISODate("2016-03-23T20:55:40.203Z"),
"allUsers" : [ ],
"user" : ""
}
Both collections have similar sizes and the same indexes:
PipelinesCluster1:SECONDARY> db.CachedUrl_319.count()
24383730
PipelinesCluster1:SECONDARY> db.CachedUrl_319.getIndexes()
[
{
"ns" : "pipelines_odd.CachedUrl_319",
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"ns" : "pipelines_odd.CachedUrl_319",
"v" : 1,
"key" : {
"updated_at" : 1
},
"name" : "updated_at_1",
"background" : true
},
{
"ns" : "pipelines_odd.CachedUrl_319",
"v" : 1,
"key" : {
"host_pattern_id" : 1
},
"name" : "host_pattern_id_1",
"background" : true
}
]
PipelinesCluster1:SECONDARY> db.CachedUrl_257.count()
24697281
PipelinesCluster1:SECONDARY> db.CachedUrl_257.getIndexes()
[
{
"ns" : "pipelines_odd.CachedUrl_257",
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"ns" : "pipelines_odd.CachedUrl_257",
"v" : 1,
"key" : {
"updated_at" : 1
},
"name" : "updated_at_1",
"background" : true
},
{
"ns" : "pipelines_odd.CachedUrl_257",
"v" : 1,
"key" : {
"host_pattern_id" : 1
},
"name" : "host_pattern_id_1",
"background" : true
}
]
I understand that query performance can vary depending on database load and other factors, but the queries against CachedUrl_319 are consistently slow, while those against CachedUrl_257 are always returned instantly. What could be causing that and is there any way to fix it?
I think you were cached for your second query.
You created an index, so mongodb automatically handled caching for you.
FAQs # mongodb.org
If you look at the second system.profile collection you posted, in the execStats
"execStats" : {
"stage" : "CACHED_PLAN", <-- you were cached
Compare it to the first one, and you will see that the first system.profile collection has different stages, e.g.
"execStats" : {
"stage" : "ENSURE_SORTED"
You can also look at the "inputStage" , and you will see the second one just fetches.
"inputStage" : {
"stage" : "FETCH",
And the first one does more work, e.g. "SORT" and "SORT_KEY_GENERATOR".