a mongodb shard shows strange slow behavior - mongodb

I'm testing below aggregate
db.getCollection('token_transfer').explain("executionStats").aggregate([
{$match: {
$and: [{"contract_address":"0xTTTTTTTTTTT"}, {"timestamp": {$gte: ISODate("2019-12-13T00:45:05.000Z")}}]
}},
{$group: {
_id: null,
transfer_count: {$sum: 1},
transfer_volume_sum: {$sum: "$value"},
}}
])
indexes of the token_transfer collection is like below
{
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
{
"tx_hash" : "hashed"
}
...
token_transfer collection has below fields
[contract_address, from, to, value, tx_hash, timestamp, ...]
shard key is like below
shard key: { "tx_hash" : "hashed" }
Key point is that it tooks 42706 executionTimeMillis at only shd2.
The other shards show under 5000 executionTimeMillis.
Why does slowness occur on certain shard which results in total query slow?
Below is my executionStats of aggregate.
/* 1 */
{
"mergeType" : "mongos",
"splitPipeline" : {
"shardsPart" : [
{
"$match" : {
"$and" : [
{
"contract_address" : {
"$eq" : "0xTTTTTTTTTTT"
}
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
}
},
{
"$group" : {
"_id" : {
"$const" : null
},
"transfer_count" : {
"$sum" : {
"$const" : 1.0
}
},
"transfer_volume_sum" : {
"$sum" : "$value"
}
}
}
],
"mergerPart" : [
{
"$group" : {
"_id" : "$$ROOT._id",
"transfer_count" : {
"$sum" : "$$ROOT.transfer_count"
},
"transfer_volume_sum" : {
"$sum" : "$$ROOT.transfer_volume_sum"
},
"$doingMerge" : true
}
}
]
},
"shards" : {
"shd3" : {
"host" : "x-db1:33333",
"stages" : [
{
"$cursor" : {
"query" : {
"$and" : [
{
"contract_address" : "0xTTTTTTTTTTT"
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
},
"fields" : {
"value" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.token_transfer",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"contract_address" : {
"$eq" : "0xTTTTTTTTTTT"
}
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"value" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
"indexName" : "contract_address_1_value_-1_timestamp_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"contract_address" : [],
"value" : [],
"timestamp" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"contract_address" : [
"[\"0xTTTTTTTTTTT\", \"0xTTTTTTTTTTT\"]"
],
"value" : [
"[MaxKey, MinKey]"
],
"timestamp" : [
"[new Date(1576197905000), new Date(9223372036854775807)]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 671,
"executionTimeMillis" : 1384,
"totalKeysExamined" : 1231507,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 671,
"executionTimeMillisEstimate" : 1370,
"works" : 1231507,
"advanced" : 671,
"needTime" : 1230835,
"needYield" : 0,
"saveState" : 9622,
"restoreState" : 9622,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"value" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 671,
"executionTimeMillisEstimate" : 1340,
"works" : 1231507,
"advanced" : 671,
"needTime" : 1230835,
"needYield" : 0,
"saveState" : 9622,
"restoreState" : 9622,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
"indexName" : "contract_address_1_value_-1_timestamp_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"contract_address" : [],
"value" : [],
"timestamp" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"contract_address" : [
"[\"0xTTTTTTTTTTT\", \"0xTTTTTTTTTTT\"]"
],
"value" : [
"[MaxKey, MinKey]"
],
"timestamp" : [
"[new Date(1576197905000), new Date(9223372036854775807)]"
]
},
"keysExamined" : 1231507,
"seeks" : 1230836,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
{
"$group" : {
"_id" : {
"$const" : null
},
"transfer_count" : {
"$sum" : {
"$const" : 1.0
}
},
"transfer_volume_sum" : {
"$sum" : "$value"
}
}
}
]
},
"shd1" : {
"host" : "x-db2:11111",
"stages" : [
{
"$cursor" : {
"query" : {
"$and" : [
{
"contract_address" : "0xTTTTTTTTTTT"
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
},
"fields" : {
"value" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.token_transfer",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"contract_address" : {
"$eq" : "0xTTTTTTTTTTT"
}
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"value" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
"indexName" : "contract_address_1_value_-1_timestamp_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"contract_address" : [],
"value" : [],
"timestamp" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"contract_address" : [
"[\"0xTTTTTTTTTTT\", \"0xTTTTTTTTTTT\"]"
],
"value" : [
"[MaxKey, MinKey]"
],
"timestamp" : [
"[new Date(1576197905000), new Date(9223372036854775807)]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 680,
"executionTimeMillis" : 4545,
"totalKeysExamined" : 1234518,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 680,
"executionTimeMillisEstimate" : 3685,
"works" : 1234518,
"advanced" : 680,
"needTime" : 1233837,
"needYield" : 0,
"saveState" : 9656,
"restoreState" : 9656,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"value" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 680,
"executionTimeMillisEstimate" : 3685,
"works" : 1234518,
"advanced" : 680,
"needTime" : 1233837,
"needYield" : 0,
"saveState" : 9656,
"restoreState" : 9656,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
"indexName" : "contract_address_1_value_-1_timestamp_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"contract_address" : [],
"value" : [],
"timestamp" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"contract_address" : [
"[\"0xTTTTTTTTTTT\", \"0xTTTTTTTTTTT\"]"
],
"value" : [
"[MaxKey, MinKey]"
],
"timestamp" : [
"[new Date(1576197905000), new Date(9223372036854775807)]"
]
},
"keysExamined" : 1234518,
"seeks" : 1233838,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
{
"$group" : {
"_id" : {
"$const" : null
},
"transfer_count" : {
"$sum" : {
"$const" : 1.0
}
},
"transfer_volume_sum" : {
"$sum" : "$value"
}
}
}
]
},
"shd2" : {
"host" : "x-db3:22222",
"stages" : [
{
"$cursor" : {
"query" : {
"$and" : [
{
"contract_address" : "0xTTTTTTTTTTT"
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
},
"fields" : {
"value" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.token_transfer",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"contract_address" : {
"$eq" : "0xTTTTTTTTTTT"
}
},
{
"timestamp" : {
"$gte" : ISODate("2019-12-13T00:45:05.000Z")
}
}
]
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"value" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
"indexName" : "contract_address_1_value_-1_timestamp_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"contract_address" : [],
"value" : [],
"timestamp" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"contract_address" : [
"[\"0xTTTTTTTTTTT\", \"0xTTTTTTTTTTT\"]"
],
"value" : [
"[MaxKey, MinKey]"
],
"timestamp" : [
"[new Date(1576197905000), new Date(9223372036854775807)]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 720,
"executionTimeMillis" : 42706,
"totalKeysExamined" : 1181569,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 720,
"executionTimeMillisEstimate" : 4284,
"works" : 1181569,
"advanced" : 720,
"needTime" : 1180848,
"needYield" : 0,
"saveState" : 9249,
"restoreState" : 9249,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"value" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 720,
"executionTimeMillisEstimate" : 4244,
"works" : 1181569,
"advanced" : 720,
"needTime" : 1180848,
"needYield" : 0,
"saveState" : 9249,
"restoreState" : 9249,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"contract_address" : 1.0,
"value" : -1.0,
"timestamp" : 1.0
},
"indexName" : "contract_address_1_value_-1_timestamp_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"contract_address" : [],
"value" : [],
"timestamp" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"contract_address" : [
"[\"0xTTTTTTTTTTT\", \"0xTTTTTTTTTTT\"]"
],
"value" : [
"[MaxKey, MinKey]"
],
"timestamp" : [
"[new Date(1576197905000), new Date(9223372036854775807)]"
]
},
"keysExamined" : 1181569,
"seeks" : 1180849,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
{
"$group" : {
"_id" : {
"$const" : null
},
"transfer_count" : {
"$sum" : {
"$const" : 1.0
}
},
"transfer_volume_sum" : {
"$sum" : "$value"
}
}
}
]
}
},
"ok" : 1.0,
"$clusterTime" : {
"clusterTime" : Timestamp(1576201630, 116),
"signature" : {
"hash" : { "$binary" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "$type" : "00" },
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1576201630, 115)
}

Related

MongoDB 4.4 slow query

I execute a query command in mongos, but it executes for a long time.
mongos> db.message.find({"toid":123,"$or":[{"rid":2},{"validtime":null},{"fromid":2},{"validtime":{"$lt":1649565335}}]}).sort({sortid:-1}).limit(10)
slow query log like this:
{
"op" : "command",
"ns" : "sns.message",
"command" : {
"explain" : {
"find" : "message",
"filter" : {
"toid" : 123,
"$or" : [
{
"rid" : 2
},
{
"validtime" : null
},
{
"fromid" : 2
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
"limit" : 10,
"singleBatch" : true,
"sort" : {
"sortid" : -1
},
"options" : {
}
},
"verbosity" : "executionStats",
"$db" : "sns"
},
"numYield" : 6477,
"locks" : {
"ReplicationStateTransition" : {
"acquireCount" : {
"w" : NumberLong(6479)
}
},
"Global" : {
"acquireCount" : {
"r" : NumberLong(6479)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(6478)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(6478)
}
},
"Mutex" : {
"acquireCount" : {
"r" : NumberLong(1)
}
}
},
"flowControl" : {
},
"storage" : {
"data" : {
"bytesRead" : NumberLong(91629495),
"timeReadingMicros" : NumberLong(68943)
}
},
"responseLength" : 5159,
"protocol" : "op_query",
"millis" : 13477,
"ts" : ISODate("2022-04-11T05:46:33.221Z"),
"client" : "127.0.0.1",
"allUsers" : [ ],
"user" : ""
}
and the explain information is as follows:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "sns.message",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"$or" : [
{
"fromid" : {
"$eq" : 2
}
},
{
"rid" : {
"$eq" : 2
}
},
{
"validtime" : {
"$eq" : null
}
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
{
"toid" : {
"$eq" : 123
}
}
]
},
"winningPlan" : {
"stage" : "LIMIT",
"limitAmount" : 10,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"$or" : [
{
"fromid" : {
"$eq" : 2
}
},
{
"rid" : {
"$eq" : 2
}
},
{
"validtime" : {
"$eq" : null
}
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
{
"toid" : {
"$eq" : 123
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"sortid" : 1,
"toid" : 1
},
"indexName" : "toid_1_sortid_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"sortid" : [ ],
"toid" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "backward",
"indexBounds" : {
"sortid" : [
"[MaxKey, MinKey]"
],
"toid" : [
"[MaxKey, MinKey]"
]
}
}
}
},
"rejectedPlans" : [
{
"stage" : "SORT",
"sortPattern" : {
"sortid" : -1
},
"memLimit" : 104857600,
"limitAmount" : 10,
"type" : "simple",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$or" : [
{
"fromid" : {
"$eq" : 2
}
},
{
"rid" : {
"$eq" : 2
}
},
{
"validtime" : {
"$eq" : null
}
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"toid" : 1
},
"indexName" : "toid_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"toid" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"toid" : [
"[123.0, 123.0]"
]
}
}
}
},
{
"stage" : "SORT",
"sortPattern" : {
"sortid" : -1
},
"memLimit" : 104857600,
"limitAmount" : 10,
"type" : "simple",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$or" : [
{
"fromid" : {
"$eq" : 2
}
},
{
"rid" : {
"$eq" : 2
}
},
{
"validtime" : {
"$eq" : null
}
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"toid" : 1,
"replyid" : 1
},
"indexName" : "toid_1_replyid_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"toid" : [ ],
"replyid" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"toid" : [
"[123.0, 123.0]"
],
"replyid" : [
"[MinKey, MaxKey]"
]
}
}
}
},
{
"stage" : "SORT",
"sortPattern" : {
"sortid" : -1
},
"memLimit" : 104857600,
"limitAmount" : 10,
"type" : "simple",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$or" : [
{
"fromid" : {
"$eq" : 2
}
},
{
"rid" : {
"$eq" : 2
}
},
{
"validtime" : {
"$eq" : null
}
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"toid" : 1,
"validtime" : 1,
"time" : 1
},
"indexName" : "toid_1_validtime_1_time_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"toid" : [ ],
"validtime" : [ ],
"time" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"toid" : [
"[123.0, 123.0]"
],
"validtime" : [
"[MinKey, MaxKey]"
],
"time" : [
"[MinKey, MaxKey]"
]
}
}
}
},
// omit...
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 10,
"executionTimeMillis" : 13477,
"totalKeysExamined" : 1295456,
"totalDocsExamined" : 1295456,
"executionStages" : {
"stage" : "LIMIT",
"nReturned" : 10,
"executionTimeMillisEstimate" : 700,
"works" : 1295457,
"advanced" : 10,
"needTime" : 1295446,
"needYield" : 0,
"saveState" : 6477,
"restoreState" : 6477,
"isEOF" : 1,
"limitAmount" : 10,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"$or" : [
{
"fromid" : {
"$eq" : 2
}
},
{
"rid" : {
"$eq" : 2
}
},
{
"validtime" : {
"$eq" : null
}
},
{
"validtime" : {
"$lt" : 1649565335
}
}
]
},
{
"toid" : {
"$eq" : 123
}
}
]
},
"nReturned" : 10,
"executionTimeMillisEstimate" : 690,
"works" : 1295456,
"advanced" : 10,
"needTime" : 1295446,
"needYield" : 0,
"saveState" : 6477,
"restoreState" : 6477,
"isEOF" : 0,
"docsExamined" : 1295456,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1295456,
"executionTimeMillisEstimate" : 188,
"works" : 1295456,
"advanced" : 1295456,
"needTime" : 0,
"needYield" : 0,
"saveState" : 6477,
"restoreState" : 6477,
"isEOF" : 0,
"keyPattern" : {
"sortid" : 1,
"toid" : 1
},
"indexName" : "toid_1_sortid_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"sortid" : [ ],
"toid" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "backward",
"indexBounds" : {
"sortid" : [
"[MaxKey, MinKey]"
],
"toid" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 1295456,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
}
},
"serverInfo" : {
"host" : "MongoDB",
"port" : 22005,
"version" : "4.4.13",
"gitVersion" : "df25c71b8674a78e17468f48bcda5285decb9246"
},
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000001")
},
"lastCommittedOpTime" : Timestamp(1649655993, 20),
"$configServerState" : {
"opTime" : {
"ts" : Timestamp(1649655992, 11),
"t" : NumberLong(1)
}
},
"$clusterTime" : {
"clusterTime" : Timestamp(1649655993, 26),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1649655993, 26)
}
in the "executionStats" block, both the "LIMIT" stage and its substage take less than or equal to 700ms, but the total time is 13477ms. what happened during this time? How can I locate the reason for the time consuming? And Looking forward to optimization suggestions.
Thanks
The total executionTimeMillis is the "total" amount of time required for both planning + execution, this means there are certain factors now calculated in the breakdown per stage.
For example:
Lock acquisition / overall db load.
When planning only a 100 document sample is examined, however as you can see for the actual query over 1milion documents are being fetched. If the there are other operations on the same collection that lock it or if the db is in general under heavy load this can affect performance as your query is waiting in line for resources.
Disk latency
As you can see your docsExamined is equal to keysExamined, this means that every single documents that matched the query needed to be fetched from disk to be examined.
This is quite a lot of overhead. and I suspect this is the main "issue" regarding performance. You could probably lower this by creating a proper compound index to satisfy this query.
You can also add a disk with more IOPS, boosting hardware will always increase performance, especially if it's at the bottleneck places.

MongoDb C# query performance

I have the MongoDB C# Driver 2.14.1 and a Mongo Server v3.6 running on a Docker container. I'm running an easy (I think) query over 3 collections. The biggest collection has 400k documents, each document averaged 64Kb. I'm filtering by two fields and returning the results in a cursor to reduce overhead. The results are sorted by descending by a field that is configured as an index as well. This is happening on my production server which is taking nearly 1GB of memory (not being released afterwards). The following queries explained (run on the server):
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "table1",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "Location1"
}
},
{
"Date" : {
"$gt" : ISODate("2021-01-18T23:00:00Z")
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "Location1"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"Date" : -1
},
"indexName" : "Date_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"Date" : [ ]
},
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"Date" : [
"[new Date(9223372036854775807), new Date(1611010800000))"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 2,
"totalKeysExamined" : 7,
"totalDocsExamined" : 7,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "Location1"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 8,
"advanced" : 1,
"needTime" : 6,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 7,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 7,
"executionTimeMillisEstimate" : 0,
"works" : 8,
"advanced" : 7,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"Date" : -1
},
"indexName" : "Date_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"Date" : [ ]
},
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"Date" : [
"[new Date(9223372036854775807), new Date(1611010800000))"
]
},
"keysExamined" : 7,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "7aa23bd7fe20",
"port" : 27018,
"version" : "3.6.18",
"gitVersion" : "2005f25eed7ed88fa698d9b800fe536bb0410ba4"
},
"ok" : 1
}
The second query:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "table2",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "02"
}
},
{
"Date" : {
"$gt" : ISODate("2021-01-18T23:00:00Z")
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "02"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"Date" : -1
},
"indexName" : "Date_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"Date" : [ ]
},
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"Date" : [
"[new Date(9223372036854775807), new Date(1611010800000))"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 63,
"totalKeysExamined" : 9896,
"totalDocsExamined" : 9896,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "02"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 50,
"works" : 9897,
"advanced" : 1,
"needTime" : 9895,
"needYield" : 0,
"saveState" : 77,
"restoreState" : 77,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 9896,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 9896,
"executionTimeMillisEstimate" : 0,
"works" : 9897,
"advanced" : 9896,
"needTime" : 0,
"needYield" : 0,
"saveState" : 77,
"restoreState" : 77,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"Date" : -1
},
"indexName" : "Date_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"Date" : [ ]
},
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"Date" : [
"[new Date(9223372036854775807), new Date(1611010800000))"
]
},
"keysExamined" : 9896,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "7aa23bd7fe20",
"port" : 27018,
"version" : "3.6.18",
"gitVersion" : "2005f25eed7ed88fa698d9b800fe536bb0410ba4"
},
"ok" : 1
}
And the third:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "table3",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "52"
}
},
{
"Date" : {
"$gt" : ISODate("2021-01-18T23:00:00Z")
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "52"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"Date" : -1
},
"indexName" : "Date_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"Date" : [ ]
},
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"Date" : [
"[new Date(9223372036854775807), new Date(1611010800000))"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 30,
"executionTimeMillis" : 934,
"totalKeysExamined" : 366370,
"totalDocsExamined" : 366370,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"Type" : {
"$eq" : "Type1"
}
},
{
"LocationId" : {
"$eq" : "52"
}
}
]
},
"nReturned" : 30,
"executionTimeMillisEstimate" : 889,
"works" : 366371,
"advanced" : 30,
"needTime" : 366340,
"needYield" : 0,
"saveState" : 2862,
"restoreState" : 2862,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 366370,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 366370,
"executionTimeMillisEstimate" : 160,
"works" : 366371,
"advanced" : 366370,
"needTime" : 0,
"needYield" : 0,
"saveState" : 2862,
"restoreState" : 2862,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"Date" : -1
},
"indexName" : "Date_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"Date" : [ ]
},
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"Date" : [
"[new Date(9223372036854775807), new Date(1611010800000))"
]
},
"keysExamined" : 366370,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "7aa23bd7fe20",
"port" : 27018,
"version" : "3.6.18",
"gitVersion" : "2005f25eed7ed88fa698d9b800fe536bb0410ba4"
},
"ok" : 1
}
Now with my little knowledge of the "explainPlan" I would have imagined that the performance is OK, and not many records get returned on each query. Having said that I can see a pattern when I run the code via the .NET application (C# code) that makes the CPU go through the roof and right after the memory follows in the Mongo server Docker container.
I don't know if there is misconfigured or whether I can do something to improve the performance of it because I'm quite puzzle with the performance on just that query - I think is this query because the rest of the queries with similar amount of data on different parts of the system work quite well. Besides that, is there any mechanism or tool I can use to diagnose the memory consumption in my Mongo server?

How to improve slow aggregate query in mongodb?

I am querying for stock tickers that match the tickers.symbol array:
db.getCollection('reads').explain("executionStats").aggregate([
{ $match: { 'tickers.symbol': { $in: ['APPL'] } } },
{
$project: {
content: 0,
htm: 0,
},
},
{
$group: {
_id: '$url',
root: { $first: '$$ROOT' },
},
},
{ $sort: { 'root.createdAt': -1 } },
{ $limit: 50 },
{ $replaceRoot: { newRoot: '$root' } },
])
/* 1 */
{
"stages" : [
{
"$cursor" : {
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "briskreader.reads",
"indexFilterSet" : false,
"parsedQuery" : {
"tickers.symbol" : {
"$eq" : "APPL"
}
},
"queryHash" : "301E9992",
"planCacheKey" : "97D88657",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"tickers.symbol" : 1.0
},
"indexName" : "tickers.symbol_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"tickers.symbol" : [
"tickers"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"tickers.symbol" : [
"[\"APPL\", \"APPL\"]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"tickers.symbol" : 1.0,
"createdAt" : -1.0
},
"indexName" : "tickers.symbol_1_createdAt_-1",
"isMultiKey" : true,
"multiKeyPaths" : {
"tickers.symbol" : [
"tickers"
],
"createdAt" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"tickers.symbol" : [
"[\"APPL\", \"APPL\"]"
],
"createdAt" : [
"[MaxKey, MinKey]"
]
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 0,
"executionTimeMillis" : 118,
"totalKeysExamined" : 0,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 0,
"executionTimeMillisEstimate" : 64,
"works" : 2,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"docsExamined" : 0,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 0,
"executionTimeMillisEstimate" : 64,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"keyPattern" : {
"tickers.symbol" : 1.0
},
"indexName" : "tickers.symbol_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"tickers.symbol" : [
"tickers"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"tickers.symbol" : [
"[\"APPL\", \"APPL\"]"
]
},
"keysExamined" : 0,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
}
},
"nReturned" : NumberLong(0),
"executionTimeMillisEstimate" : NumberLong(0)
},
{
"$project" : {
"content" : false,
"htm" : false
},
"nReturned" : NumberLong(0),
"executionTimeMillisEstimate" : NumberLong(0)
},
{
"$group" : {
"_id" : "$url",
"root" : {
"$first" : "$$ROOT"
}
},
"nReturned" : NumberLong(0),
"executionTimeMillisEstimate" : NumberLong(0)
},
{
"$sort" : {
"sortKey" : {
"root.createdAt" : -1
},
"limit" : NumberLong(50)
},
"nReturned" : NumberLong(0),
"executionTimeMillisEstimate" : NumberLong(0)
},
{
"$replaceRoot" : {
"newRoot" : "$root"
},
"nReturned" : NumberLong(0),
"executionTimeMillisEstimate" : NumberLong(0)
}
],
"serverInfo" : {
"host" : "4da40b419852",
"port" : 27017,
"version" : "4.4.3",
"gitVersion" : "913d6b62acfbb344dde1b116f4161360acd8fd13"
},
"ok" : 1.0
}
Here is an example doc:
/* 2 */
{
"_id" : ObjectId("60073943ef54cc001c61ee7e"),
"summary" : {
"topics" : [
"brain",
"virus",
"mice",
"kumar",
"lungs",
"covid19",
"disease",
"symptoms",
"severe",
"illness"
],
"sentiment" : -0.0384615384615385,
"words" : 605,
"difficulty" : 0.766666666666667,
"minutes" : 5
},
"views" : 1,
"title" : "Study finds COVID-19 attack on brain, not lungs, triggers severe disease in mice: The findings have implications for understanding the wide range in symptoms and severity of illness among humans who are infected by SARS-CoV-2",
"byline" : null,
"dir" : null,
"length" : 3333,
"excerpt" : "Researchers have found that infecting the nasal passages of mice with the virus that causes COVID-19 led to a rapid, escalating attack on the brain that triggered severe illness, even after the lungs were successfully clearing themselves of the virus.",
"siteName" : "ScienceDaily",
"tickers" : [
{
"_id" : ObjectId("6007393aef54cc001c61ee7a"),
"name" : "Visa Inc.",
"symbol" : "V",
"exchange" : "nyse"
}
],
"cryptos" : [],
"meta" : {
"title" : "Study finds COVID-19 attack on brain, not lungs, triggers severe disease in mice: The findings have implications for understanding the wide range in symptoms and severity of illness among humans who are infected by SARS-CoV-2 -- ScienceDaily",
"thumb" : "https://www.sciencedaily.com/images/scidaily-icon.png"
},
"url" : "https://www.sciencedaily.com/releases/2021/01/210119114456.htm",
"host" : "www.sciencedaily.com",
"createdAt" : ISODate("2021-01-19T19:55:47.433Z"),
"updatedAt" : ISODate("2021-01-19T19:55:47.433Z"),
"shortId" : "9RVS9YmfYeY",
"__v" : 0
}
The query works with small collections (dev) but in prod with 100k docs it timesout after 300 seconds.
As long as there is an index on createdAt, moving sort before project will do.
move project after limit
db.getCollection('reads').explain("executionStats").aggregate([
{ $match: { 'tickers.symbol': {$in:['APPL']} } },
{ $sort: { 'createdAt': -1 } },
{
$group: {
_id: '$url',
root: { $first: '$$ROOT' },
},
},
{ $limit: 50 },
{
$project: {
"root.content": 0,
"root.htm": 0,
},
},
{ $replaceRoot: { newRoot: '$root' } },
])
$in
As it is written { 'tickers.symbol': {$in:['APPL'] }} should be written { 'tickers.symbol': 'APPL' }. But for many values, keep the original syntax.

MongoDB index doing a collection scan instead index scan [duplicate]

Here are the compound index and single index I have for this Collection:
///db.Collection.getIndexes()
/* 1 */
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "service.Collection"
},
/* 2 */
{
"v" : 2,
"key" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"name" : "FirstIdSecondIdCreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"ns" : "service.Collection"
},
/* 3 */
{
"v" : 2,
"key" : {
"CreationTime" : 1
},
"name" : "CreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"ns" : "service.Collection"
}
The expected result is an IXSCAN using the FirstIdSecondIdCreationTime index:
///service.Collection.find({ FirstId: "771367b7-4bef-49ab-bda1-6230254c6349", ///SecondId: "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f" })
/// .projection({})
/// .sort({_id:-1}).hint("FirstIdSecondIdCreationTime").explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "service.Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"_id" : -1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"indexName" : "FirstIdSecondIdCreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : false,
"multiKeyPaths" : {
"FirstId" : [ ],
"SecondId" : [ ],
"CreationTime" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"FirstId" : [
"[MinKey, MaxKey]"
],
"SecondId" : [
"[MinKey, MaxKey]"
],
"CreationTime" : [
"[MaxKey, MinKey]"
]
}
}
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 5491,
"totalKeysExamined" : 856730,
"totalDocsExamined" : 856730,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 1,
"executionTimeMillisEstimate" : 5261,
"works" : 856734,
"advanced" : 1,
"needTime" : 856732,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"_id" : -1
},
"memUsage" : 432,
"memLimit" : 33554432,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"nReturned" : 1,
"executionTimeMillisEstimate" : 5201,
"works" : 856732,
"advanced" : 1,
"needTime" : 856730,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 5131,
"works" : 856731,
"advanced" : 1,
"needTime" : 856729,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 856730,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 856730,
"executionTimeMillisEstimate" : 820,
"works" : 856731,
"advanced" : 856730,
"needTime" : 0,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"indexName" : "FirstIdSecondIdCreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : false,
"multiKeyPaths" : {
"FirstId" : [ ],
"SecondId" : [ ],
"CreationTime" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"FirstId" : [
"[MinKey, MaxKey]"
],
"SecondId" : [
"[MinKey, MaxKey]"
],
"CreationTime" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 856730,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"indexDef" : {
"indexName" : "FirstIdSecondIdCreationTime",
"isMultiKey" : false,
"multiKeyPaths" : {
"FirstId" : [ ],
"SecondId" : [ ],
"CreationTime" : [ ]
},
"keyPattern" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"direction" : "forward"
}
}
}
}
}
but the actual result is a COLLSCAN that takes over 8000ms:
"event": {
"dataset": "mongodb.log",
"module": "mongodb"
},
"service": {
"type": "mongodb"
},
"message": "command service.Collection command: find { find: \"Collection\",
filter: { FirstId: \"771367b7-4bef-49ab-bda1-6230254c6349\", SecondId: \"3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f\" }, sort: { CreationTime: -1 }, limit: 1,
planSummary: COLLSCAN keysExamined:0 docsExamined:784787 hasSortStage:1 cursorExhausted:1 numYields:6175 nreturned:1 reslen:677
locks:{ Global: { acquireCount: { r: 12352 } }, Database: { acquireCount: { r: 6176 } }, Collection: { acquireCount: { r: 6176 } } } protocol:op_msg 8441ms",
"mongodb.docsExamined": 784787,
"fileset": {
"name": "log"
},
Why am I COLLSCANing instead of IXSCANing with the FirstIdSecondIDCreationTime compound index? Is there a way to change my index/ my query to speed up the query?
Per a suggestion in the comments, I've run explain("allPlansExecution").
///db.Collection.find({ FirstId: "771367b7-4bef-49ab-bda1-6230254c6349", ///SecondId: "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f" })
/// .projection({})
/// .sort({_id:-1}).explain('allPlansExecution')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "service.Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 5408,
"totalKeysExamined" : 856748,
"totalDocsExamined" : 856748,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 4862,
"works" : 856749,
"advanced" : 1,
"needTime" : 856747,
"needYield" : 0,
"saveState" : 6694,
"restoreState" : 6694,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 856748,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 856748,
"executionTimeMillisEstimate" : 1220,
"works" : 856749,
"advanced" : 856748,
"needTime" : 0,
"needYield" : 0,
"saveState" : 6694,
"restoreState" : 6694,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 856748,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
},
"allPlansExecution" : [ ]
}
}
The "FirstIdSecondIdCreationTime" index was not automatically considered because it was created with a collation, and the query is being run without a collation.
Use the .collation() cursor method to specify the same collation for the query that was used for the index.
The 5.5 second run time using that index is pretty slow as well.
You may see some improvement in that query if you create an index on {FirstId: 1, SecondId: 1, _id: 1} so that they query executor can use the index to meet the sort instead of an in-memory sort.
Can you please sort by leading indexes i.e firstId, secondId and creationTime in the same sequence and see index is used. it will give an idea whether leading indexes fields should be there in sort as well.

MongoDB query index scan not filtering as expected

I have a query that uses an index but during the fetch is looking up too many documents.
The index in question is:
{
“v” : 2,
“key” : {
“vw” : -1,
“if” : 1,
“sa” : 1,
“dd” : -1,
“ca” : 1
},
“name” : “Viewed_By_Category”,
“ns” : “redacted”,
“background” : false
}
the query in question:
db.stories.find({ 'if': {$ne: true}, 'sa': 2, 'dd': {$ne : null}, 'ca': 11}).skip(3990).limit(30).sort({'vw':-1}).explain('executionStats')*
and this is the explain output:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "lushstories.stories",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"ca" : {
"$eq" : 11
}
},
{
"sa" : {
"$eq" : 2
}
},
{
"dd" : {
"$not" : {
"$eq" : null
}
}
},
{
"if" : {
"$not" : {
"$eq" : true
}
}
}
]
},
"winningPlan" : {
"stage" : "LIMIT",
"limitAmount" : 30,
"inputStage" : {
"stage" : "SKIP",
"skipAmount" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"ca" : {
"$eq" : 11
}
},
{
"sa" : {
"$eq" : 2
}
},
{
"dd" : {
"$not" : {
"$eq" : null
}
}
},
{
"if" : {
"$not" : {
"$eq" : true
}
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"vw" : -1,
"if" : 1,
"sa" : 1,
"dd" : -1,
"ca" : 1
},
"indexName" : "Viewed_By_Category",
"isMultiKey" : false,
"multiKeyPaths" : {
"vw" : [ ],
"if" : [ ],
"sa" : [ ],
"dd" : [ ],
"ca" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"vw" : [
"[MaxKey, MinKey]"
],
"if" : [
"[MinKey, MaxKey]"
],
"sa" : [
"[MinKey, MaxKey]"
],
"dd" : [
"[MaxKey, MinKey]"
],
"ca" : [
"[MinKey, MaxKey]"
]
}
}
}
}
},
"rejectedPlans" : [
{
"stage" : "SKIP",
"skipAmount" : 3990,
"inputStage" : {
"stage" : "SORT",
"sortPattern" : {
"vw" : -1
},
"limitAmount" : 4020,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"dd" : {
"$not" : {
"$eq" : null
}
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"dd" : -1,
"if" : 1,
"sa" : 1,
"ca" : 1,
"ha" : 1
},
"indexName" : "Story_Visible_With_Audio",
"isMultiKey" : false,
"multiKeyPaths" : {
"dd" : [ ],
"if" : [ ],
"sa" : [ ],
"ca" : [ ],
"ha" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"dd" : [
"[MaxKey, null)",
"(null, MinKey]"
],
"if" : [
"[MinKey, true)",
"(true, MaxKey]"
],
"sa" : [
"[2.0, 2.0]"
],
"ca" : [
"[11.0, 11.0]"
],
"ha" : [
"[MinKey, MaxKey]"
]
}
}
}
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 30,
"executionTimeMillis" : 5500,
"totalKeysExamined" : 55743,
"totalDocsExamined" : 55743,
"executionStages" : {
"stage" : "LIMIT",
"nReturned" : 30,
"executionTimeMillisEstimate" : 5372,
"works" : 55744,
"advanced" : 30,
"needTime" : 55713,
"needYield" : 0,
"saveState" : 565,
"restoreState" : 565,
"isEOF" : 1,
"invalidates" : 0,
"limitAmount" : 30,
"inputStage" : {
"stage" : "SKIP",
"nReturned" : 30,
"executionTimeMillisEstimate" : 5372,
"works" : 55743,
"advanced" : 30,
"needTime" : 55713,
"needYield" : 0,
"saveState" : 565,
"restoreState" : 565,
"isEOF" : 0,
"invalidates" : 0,
"skipAmount" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"ca" : {
"$eq" : 11
}
},
{
"sa" : {
"$eq" : 2
}
},
{
"dd" : {
"$not" : {
"$eq" : null
}
}
},
{
"if" : {
"$not" : {
"$eq" : true
}
}
}
]
},
"nReturned" : 4020,
"executionTimeMillisEstimate" : 5372,
"works" : 55743,
"advanced" : 4020,
"needTime" : 51723,
"needYield" : 0,
"saveState" : 565,
"restoreState" : 565,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 55743,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 55743,
"executionTimeMillisEstimate" : 80,
"works" : 55743,
"advanced" : 55743,
"needTime" : 0,
"needYield" : 0,
"saveState" : 565,
"restoreState" : 565,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"vw" : -1,
"if" : 1,
"sa" : 1,
"dd" : -1,
"ca" : 1
},
"indexName" : "Viewed_By_Category",
"isMultiKey" : false,
"multiKeyPaths" : {
"vw" : [ ],
"if" : [ ],
"sa" : [ ],
"dd" : [ ],
"ca" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"vw" : [
"[MaxKey, MinKey]"
],
"if" : [
"[MinKey, MaxKey]"
],
"sa" : [
"[MinKey, MaxKey]"
],
"dd" : [
"[MaxKey, MinKey]"
],
"ca" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 55743,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
"serverInfo" : {
"host" : "redacted",
"port" : 27017,
"version" : "4.0.9",
"gitVersion" : "fc525e2d9b0e4bceff5c2201457e564362909765"
},
"ok" : 1
}
So why is the IXSCAN scan stage not using any of the predicates to filter, the indexBounds are all using [MaxKey, MinKey]
This is returning the full number of records 55743 which is being fed into the fetch.
Is there something I don't understand about these indexes?
Thanks
That is happening because your query does not specify any match criteria for the first field in the index.
MongoDB does not store each field of the index separately. It is a single tree where the values are concatenated to for the index entry. In order to use the index on {"vw" : -1, "if" : 1, "sa" : 1, "dd" : -1, "ca" : 1} to process that query, it has to examine every value of vw.
This index allows the query executor to use the index to satisfy the sort, so no in-memory sort is needed. If you rerun that explain using "allPlansExecution", you can compare how much faster this is than the rejected plan that needs a sort stage.
The most efficient index for a query follows the equality-sort-range rule, meaning the fields that the query will be matching with exact values should be listed first, then the sort field(s), and then any fields with ranged or not-equal predicates.
If you create an index on {"ca" : 1, "sa" : 1, "vw":-1, "dd" : -1, "if" : 1} you should find that the query completes much faster.
The answer by Joe explains it perfectly, just to add you have a condition in your query
{$ne : null}
It can still trigger filter operation in Mongo (version dependent). Current version can accommodate it in index scan 4.2.6.