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

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

    XMLWordPrintable

    Details

    • Backwards Compatibility:
      Minor Change
    • Epic Link:
    • Sprint:
      Query 2017-02-13, Query 2017-03-27
    • Case:

      Description

      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.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              david.storch David Storch
              Reporter:
              david.storch David Storch
              Participants:
              Votes:
              29 Vote for this issue
              Watchers:
              31 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: