Created
August 19, 2020 19:46
-
-
Save evan-stripe/df24064abc5d61d665d0f4daf2cdbe5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> db.test.save({a: 1}) | |
WriteResult({ "nInserted" : 1 }) | |
> db.test.save({a: 2}) | |
WriteResult({ "nInserted" : 1 }) | |
> db.test.save({a: 3}) | |
WriteResult({ "nInserted" : 1 }) | |
> db.test.runCommand({find: 'test', filter: {a: {$gte: 2}}, includeExecutionStats: true}) | |
{ | |
"cursor" : { | |
"firstBatch" : [ | |
{ | |
"_id" : ObjectId("5f35bb945edc03d8581bd9c4"), | |
"a" : 2 | |
}, | |
{ | |
"_id" : ObjectId("5f35bb955edc03d8581bd9c5"), | |
"a" : 3 | |
} | |
], | |
"id" : NumberLong(0), | |
"ns" : "test.test" | |
}, | |
"executionStats" : { | |
"keysExamined" : 0, | |
"docsExamined" : 3, | |
"hasSortStage" : false, | |
"planSummary" : "COLLSCAN" | |
}, | |
"ok" : 1 | |
} | |
> db.test.ensureIndex({a: 1}) | |
{ | |
"createdCollectionAutomatically" : false, | |
"numIndexesBefore" : 1, | |
"numIndexesAfter" : 2, | |
"ok" : 1 | |
} | |
> db.test.runCommand({find: 'test', filter: {a: {$gte: 2}}, includeExecutionStats: true}) | |
{ | |
"cursor" : { | |
"firstBatch" : [ | |
{ | |
"_id" : ObjectId("5f35bb945edc03d8581bd9c4"), | |
"a" : 2 | |
}, | |
{ | |
"_id" : ObjectId("5f35bb955edc03d8581bd9c5"), | |
"a" : 3 | |
} | |
], | |
"id" : NumberLong(0), | |
"ns" : "test.test" | |
}, | |
"executionStats" : { | |
"keysExamined" : 2, | |
"docsExamined" : 2, | |
"hasSortStage" : false, | |
"planSummary" : "IXSCAN { a: 1 }" | |
}, | |
"ok" : 1 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp | |
index cba4f1d224..22c7caaff7 100644 | |
--- a/src/mongo/db/commands/find_cmd.cpp | |
+++ b/src/mongo/db/commands/find_cmd.cpp | |
@@ -483,6 +483,15 @@ public: | |
throw; | |
} | |
+ // Need to grab the stats now before we capture the cursor | |
+ PlanSummaryStats summaryStats; | |
+ std::string planSummary; | |
+ bool includeExecutionStats(originalQR.getIncludeExecutionStats()); | |
+ if (includeExecutionStats) { | |
+ exec->getSummaryStats(&summaryStats); | |
+ planSummary = exec->getPlanSummary(); | |
+ } | |
+ | |
// Set up the cursor for getMore. | |
CursorId cursorId = 0; | |
if (shouldSaveCursor(opCtx, collection, state, exec.get())) { | |
@@ -523,6 +532,17 @@ public: | |
// Generate the response object to send to the client. | |
firstBatch.done(cursorId, nss.ns()); | |
+ | |
+ // Now that the cursor response is closed, we can add the execution stats we captured | |
+ // above | |
+ if (includeExecutionStats) { | |
+ auto bodyBuilder = result->getBodyBuilder(); | |
+ BSONObjBuilder executionStatsBuilder(bodyBuilder.subobjStart("executionStats")); | |
+ executionStatsBuilder.appendNumber("keysExamined", summaryStats.totalKeysExamined); | |
+ executionStatsBuilder.appendNumber("docsExamined", summaryStats.totalDocsExamined); | |
+ executionStatsBuilder.appendBool("hasSortStage", summaryStats.hasSortStage); | |
+ executionStatsBuilder.append("planSummary", planSummary); | |
+ } | |
} | |
void appendMirrorableRequest(BSONObjBuilder* bob) const override { | |
diff --git a/src/mongo/db/query/query_request.cpp b/src/mongo/db/query/query_request.cpp | |
index b9601a5a1f..2f82416b89 100644 | |
--- a/src/mongo/db/query/query_request.cpp | |
+++ b/src/mongo/db/query/query_request.cpp | |
@@ -251,6 +251,13 @@ StatusWith<std::unique_ptr<QueryRequest>> QueryRequest::parseFromFindCommand( | |
} | |
qr->_showRecordId = el.boolean(); | |
+ } else if (fieldName == kIncludeExecutionStatsField) { | |
+ Status status = checkFieldType(el, Bool); | |
+ if (!status.isOK()) { | |
+ return status; | |
+ } | |
+ | |
+ qr->_includeExecutionStats = el.boolean(); | |
} else if (fieldName == kTailableField) { | |
Status status = checkFieldType(el, Bool); | |
if (!status.isOK()) { | |
@@ -499,6 +506,10 @@ void QueryRequest::asFindCommandInternal(BSONObjBuilder* cmdBuilder) const { | |
cmdBuilder->append(kShowRecordIdField, true); | |
} | |
+ if (_includeExecutionStats) { | |
+ cmdBuilder->append(kIncludeExecutionStatsField, true); | |
+ } | |
+ | |
switch (_tailableMode) { | |
case TailableModeEnum::kTailable: { | |
cmdBuilder->append(kTailableField, true); | |
diff --git a/src/mongo/db/query/query_request.h b/src/mongo/db/query/query_request.h | |
index bfb9615dbc..1666e761ae 100644 | |
--- a/src/mongo/db/query/query_request.h | |
+++ b/src/mongo/db/query/query_request.h | |
@@ -82,6 +82,7 @@ public: | |
static constexpr auto kResumeAfterField = "$_resumeAfter"; | |
static constexpr auto kUse44SortKeys = "_use44SortKeys"; | |
static constexpr auto kMaxTimeMSOpOnlyField = "maxTimeMSOpOnly"; | |
+ static constexpr auto kIncludeExecutionStatsField = "includeExecutionStats"; | |
// Field names for sorting options. | |
static constexpr auto kNaturalSortField = "$natural"; | |
@@ -449,6 +450,14 @@ public: | |
_resumeAfter = resumeAfter; | |
} | |
+ bool getIncludeExecutionStats() const { | |
+ return _includeExecutionStats; | |
+ } | |
+ | |
+ void setIncludeExecutionStats(bool includeExecutionStats) { | |
+ _includeExecutionStats = includeExecutionStats; | |
+ } | |
+ | |
/** | |
* Return options as a bit vector. | |
*/ | |
@@ -575,6 +584,10 @@ private: | |
// inside $expr. | |
boost::optional<BSONObj> _letParameters; | |
+ // If specified, include explain-style query execution stats as part of the | |
+ // find return value | |
+ bool _includeExecutionStats = false; | |
+ | |
// Options that can be specified in the OP_QUERY 'flags' header. | |
TailableModeEnum _tailableMode = TailableModeEnum::kNormal; | |
bool _slaveOk = false; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment