Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-19758

Add "executionStats" and "allPlansExecution" explain modes to aggregation explain

    • Minor Change
    • Query 2017-02-13, Query 2017-03-27

      We should extend aggregation explain to report the appropriate information in "executionStats" and "allPlansExecution" explain modes. In "executionStats" mode, the $cursor stage will report detailed information in the same format as used for the explaining other supported commands (find, count, etc.):

      > db.c.drop();
      > for (let i = 0; i < 10; i++) { db.c.insert({_id: i, a: 1, b: i}); }
      > db.c.createIndex({a: 1});
      > db.c.createIndex({b: 1});
      
      > db.c.explain("executionStats").aggregate([{$match: {a: 1, b: {$gt: 3}}}]);
      {
      	"stages" : [
      		{
      			"$cursor" : {
      				"query" : {
      					"a" : 1,
      					"b" : {
      						"$gt" : 3
      					}
      				},
      				"queryPlanner" : {
      					"plannerVersion" : 1,
      					"namespace" : "test.c",
      					"indexFilterSet" : false,
      					"parsedQuery" : {
      						"$and" : [
      							{
      								"a" : {
      									"$eq" : 1
      								}
      							},
      							{
      								"b" : {
      									"$gt" : 3
      								}
      							}
      						]
      					},
      					"winningPlan" : {
      						"stage" : "FETCH",
      						"filter" : {
      							"a" : {
      								"$eq" : 1
      							}
      						},
      						"inputStage" : {
      							"stage" : "IXSCAN",
      							"keyPattern" : {
      								"b" : 1
      							},
      							"indexName" : "b_1",
      							"isMultiKey" : false,
      							"multiKeyPaths" : {
      								"b" : [ ]
      							},
      							"isUnique" : false,
      							"isSparse" : false,
      							"isPartial" : false,
      							"indexVersion" : 2,
      							"direction" : "forward",
      							"indexBounds" : {
      								"b" : [
      									"(3.0, inf.0]"
      								]
      							}
      						}
      					},
      					"rejectedPlans" : [
      						{
      							"stage" : "FETCH",
      							"filter" : {
      								"b" : {
      									"$gt" : 3
      								}
      							},
      							"inputStage" : {
      								"stage" : "IXSCAN",
      								"keyPattern" : {
      									"a" : 1
      								},
      								"indexName" : "a_1",
      								"isMultiKey" : false,
      								"multiKeyPaths" : {
      									"a" : [ ]
      								},
      								"isUnique" : false,
      								"isSparse" : false,
      								"isPartial" : false,
      								"indexVersion" : 2,
      								"direction" : "forward",
      								"indexBounds" : {
      									"a" : [
      										"[1.0, 1.0]"
      									]
      								}
      							}
      						}
      					]
      				},
      				"executionStats" : {
      					"executionSuccess" : true,
      					"nReturned" : 6,
      					"executionTimeMillis" : 1,
      					"totalKeysExamined" : 6,
      					"totalDocsExamined" : 6,
      					"executionStages" : {
      						"stage" : "FETCH",
      						"filter" : {
      							"a" : {
      								"$eq" : 1
      							}
      						},
      						"nReturned" : 6,
      						"executionTimeMillisEstimate" : 0,
      						"works" : 8,
      						"advanced" : 6,
      						"needTime" : 0,
      						"needYield" : 0,
      						"saveState" : 1,
      						"restoreState" : 1,
      						"isEOF" : 1,
      						"invalidates" : 0,
      						"docsExamined" : 6,
      						"alreadyHasObj" : 0,
      						"inputStage" : {
      							"stage" : "IXSCAN",
      							"nReturned" : 6,
      							"executionTimeMillisEstimate" : 0,
      							"works" : 7,
      							"advanced" : 6,
      							"needTime" : 0,
      							"needYield" : 0,
      							"saveState" : 1,
      							"restoreState" : 1,
      							"isEOF" : 1,
      							"invalidates" : 0,
      							"keyPattern" : {
      								"b" : 1
      							},
      							"indexName" : "b_1",
      							"isMultiKey" : false,
      							"multiKeyPaths" : {
      								"b" : [ ]
      							},
      							"isUnique" : false,
      							"isSparse" : false,
      							"isPartial" : false,
      							"indexVersion" : 2,
      							"direction" : "forward",
      							"indexBounds" : {
      								"b" : [
      									"(3.0, inf.0]"
      								]
      							},
      							"keysExamined" : 6,
      							"seeks" : 1,
      							"dupsTested" : 0,
      							"dupsDropped" : 0,
      							"seenInvalidated" : 0
      						}
      					}
      				}
      			}
      		}
      	],
      	"ok" : 1,
      	"operationTime" : Timestamp(0, 0)
      }
      

      The stages[0].$cursor.executionStats section is entirely new. In "allPlansExecution" mode, the executionStats section is extended with information on all candidate plans evaluated by the plan ranker:

      > db.c.explain("allPlansExecution").aggregate([{$match: {a: 1, b: {$gt: 3}}}])
      {
      > db.c.explain("allPlansExecution").aggregate([{$match: {a: 1, b: {$gt: 3}}}])
      {
      	"stages" : [
      		{
      			"$cursor" : {
      				"query" : {
      					"a" : 1,
      					"b" : {
      						"$gt" : 3
      					}
      				},
      				"queryPlanner" : {
      					"plannerVersion" : 1,
      					"namespace" : "test.c",
      					"indexFilterSet" : false,
      					"parsedQuery" : {
      						"$and" : [
      							{
      								"a" : {
      									"$eq" : 1
      								}
      							},
      							{
      								"b" : {
      									"$gt" : 3
      								}
      							}
      						]
      					},
      					"winningPlan" : {
      						"stage" : "FETCH",
      						"filter" : {
      							"a" : {
      								"$eq" : 1
      							}
      						},
      						"inputStage" : {
      							"stage" : "IXSCAN",
      							"keyPattern" : {
      								"b" : 1
      							},
      							"indexName" : "b_1",
      							"isMultiKey" : false,
      							"multiKeyPaths" : {
      								"b" : [ ]
      							},
      							"isUnique" : false,
      							"isSparse" : false,
      							"isPartial" : false,
      							"indexVersion" : 2,
      							"direction" : "forward",
      							"indexBounds" : {
      								"b" : [
      									"(3.0, inf.0]"
      								]
      							}
      						}
      					},
      					"rejectedPlans" : [
      						{
      							"stage" : "FETCH",
      							"filter" : {
      								"b" : {
      									"$gt" : 3
      								}
      							},
      							"inputStage" : {
      								"stage" : "IXSCAN",
      								"keyPattern" : {
      									"a" : 1
      								},
      								"indexName" : "a_1",
      								"isMultiKey" : false,
      								"multiKeyPaths" : {
      									"a" : [ ]
      								},
      								"isUnique" : false,
      								"isSparse" : false,
      								"isPartial" : false,
      								"indexVersion" : 2,
      								"direction" : "forward",
      								"indexBounds" : {
      									"a" : [
      										"[1.0, 1.0]"
      									]
      								}
      							}
      						}
      					]
      				},
      				"executionStats" : {
      					"executionSuccess" : true,
      					"nReturned" : 6,
      					"executionTimeMillis" : 0,
      					"totalKeysExamined" : 6,
      					"totalDocsExamined" : 6,
      					"executionStages" : {
      						"stage" : "FETCH",
      						"filter" : {
      							"a" : {
      								"$eq" : 1
      							}
      						},
      						"nReturned" : 6,
      						"executionTimeMillisEstimate" : 0,
      						"works" : 8,
      						"advanced" : 6,
      						"needTime" : 0,
      						"needYield" : 0,
      						"saveState" : 1,
      						"restoreState" : 1,
      						"isEOF" : 1,
      						"invalidates" : 0,
      						"docsExamined" : 6,
      						"alreadyHasObj" : 0,
      						"inputStage" : {
      							"stage" : "IXSCAN",
      							"nReturned" : 6,
      							"executionTimeMillisEstimate" : 0,
      							"works" : 7,
      							"advanced" : 6,
      							"needTime" : 0,
      							"needYield" : 0,
      							"saveState" : 1,
      							"restoreState" : 1,
      							"isEOF" : 1,
      							"invalidates" : 0,
      							"keyPattern" : {
      								"b" : 1
      							},
      							"indexName" : "b_1",
      							"isMultiKey" : false,
      							"multiKeyPaths" : {
      								"b" : [ ]
      							},
      							"isUnique" : false,
      							"isSparse" : false,
      							"isPartial" : false,
      							"indexVersion" : 2,
      							"direction" : "forward",
      							"indexBounds" : {
      								"b" : [
      									"(3.0, inf.0]"
      								]
      							},
      							"keysExamined" : 6,
      							"seeks" : 1,
      							"dupsTested" : 0,
      							"dupsDropped" : 0,
      							"seenInvalidated" : 0
      						}
      					},
      					"allPlansExecution" : [
      						{
      							"nReturned" : 3,
      							"executionTimeMillisEstimate" : 0,
      							"totalKeysExamined" : 7,
      							"totalDocsExamined" : 7,
      							"executionStages" : {
      								"stage" : "FETCH",
      								"filter" : {
      									"b" : {
      										"$gt" : 3
      									}
      								},
      								"nReturned" : 3,
      								"executionTimeMillisEstimate" : 0,
      								"works" : 7,
      								"advanced" : 3,
      								"needTime" : 4,
      								"needYield" : 0,
      								"saveState" : 1,
      								"restoreState" : 1,
      								"isEOF" : 0,
      								"invalidates" : 0,
      								"docsExamined" : 7,
      								"alreadyHasObj" : 0,
      								"inputStage" : {
      									"stage" : "IXSCAN",
      									"nReturned" : 7,
      									"executionTimeMillisEstimate" : 0,
      									"works" : 7,
      									"advanced" : 7,
      									"needTime" : 0,
      									"needYield" : 0,
      									"saveState" : 1,
      									"restoreState" : 1,
      									"isEOF" : 0,
      									"invalidates" : 0,
      									"keyPattern" : {
      										"a" : 1
      									},
      									"indexName" : "a_1",
      									"isMultiKey" : false,
      									"multiKeyPaths" : {
      										"a" : [ ]
      									},
      									"isUnique" : false,
      									"isSparse" : false,
      									"isPartial" : false,
      									"indexVersion" : 2,
      									"direction" : "forward",
      									"indexBounds" : {
      										"a" : [
      											"[1.0, 1.0]"
      										]
      									},
      									"keysExamined" : 7,
      									"seeks" : 1,
      									"dupsTested" : 0,
      									"dupsDropped" : 0,
      									"seenInvalidated" : 0
      								}
      							}
      						},
      						{
      							"nReturned" : 6,
      							"executionTimeMillisEstimate" : 0,
      							"totalKeysExamined" : 6,
      							"totalDocsExamined" : 6,
      							"executionStages" : {
      								"stage" : "FETCH",
      								"filter" : {
      									"a" : {
      										"$eq" : 1
      									}
      								},
      								"nReturned" : 6,
      								"executionTimeMillisEstimate" : 0,
      								"works" : 7,
      								"advanced" : 6,
      								"needTime" : 0,
      								"needYield" : 0,
      								"saveState" : 1,
      								"restoreState" : 1,
      								"isEOF" : 1,
      								"invalidates" : 0,
      								"docsExamined" : 6,
      								"alreadyHasObj" : 0,
      								"inputStage" : {
      									"stage" : "IXSCAN",
      									"nReturned" : 6,
      									"executionTimeMillisEstimate" : 0,
      									"works" : 7,
      									"advanced" : 6,
      									"needTime" : 0,
      									"needYield" : 0,
      									"saveState" : 1,
      									"restoreState" : 1,
      									"isEOF" : 1,
      									"invalidates" : 0,
      									"keyPattern" : {
      										"b" : 1
      									},
      									"indexName" : "b_1",
      									"isMultiKey" : false,
      									"multiKeyPaths" : {
      										"b" : [ ]
      									},
      									"isUnique" : false,
      									"isSparse" : false,
      									"isPartial" : false,
      									"indexVersion" : 2,
      									"direction" : "forward",
      									"indexBounds" : {
      										"b" : [
      											"(3.0, inf.0]"
      										]
      									},
      									"keysExamined" : 6,
      									"seeks" : 1,
      									"dupsTested" : 0,
      									"dupsDropped" : 0,
      									"seenInvalidated" : 0
      								}
      							}
      						}
      					]
      				}
      			}
      		}
      	],
      	"ok" : 1,
      	"operationTime" : Timestamp(0, 0)
      }
      

      Here, the stages[0].$cursor.executionStats.allPlansExecution section is entirely new. This is implemented by allowing the explain command to accept a nested aggregate command:

      {explain: {aggregate: ...}, verbosity: "allPlansExecution"}
      

      The aggregate command's explain parameter is still supported, as in {aggregate: "myCollection", pipeline: [], explain: true}. However, the explain command format is preferred. It is illegal to combine the two formats, as in

      {explain: {aggregate: "myCollection", pipeline: [], explain: true}, verbosity: "allPlansExecution"}
      

      Finally, since the explain command has never supported readConcern or writeConcern, we have made it an error to use readConcern or writeConcern in combination with the aggregate command explain flag. All of the following examples are illegal:

      {aggregate: "myCollection", pipeline: [{$out: "foo"}], explain: true, writeConcern: {w: 1}}
      {explain: {aggregate: "myCollection", pipeline: [{$out: "foo"}]}, writeConcern: {w: 1}}
      {aggregate: "myCollection", pipeline: [{$out: "foo"}], explain: true, readConcern: {level: "majority"}}
      {explain: {aggregate: "myCollection", pipeline: [{$out: "foo"}]}, readConcern: {level: "majority"}}
      

      This is a minor breaking change in 3.6 which will have to be accommodated by drivers.

      Note that aggregation stages other than $cursor do not currently report execution stats. Implementing this is further work tracked by SERVER-21784.

            Assignee:
            david.storch@mongodb.com David Storch
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            29 Vote for this issue
            Watchers:
            30 Start watching this issue

              Created:
              Updated:
              Resolved: