summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJames Wahlin <james.wahlin@10gen.com>2016-04-06 14:45:29 -0400
committerJames Wahlin <james.wahlin@10gen.com>2016-04-20 13:22:35 -0400
commit0f1cf1b71a12d2e41aeea064848ef192bfceddd7 (patch)
treea563d427ab4126a5fb05834f1d9dc9e6c0ed7ae6 /src/mongo
parent5dd37d3fa197e73fab8298e5d748e06393b053b2 (diff)
downloadmongo-0f1cf1b71a12d2e41aeea064848ef192bfceddd7.tar.gz
SERVER-23257 Report keysExamined/docsExamined/hasSortStage where valid
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/commands/count_cmd.cpp4
-rw-r--r--src/mongo/db/commands/distinct.cpp4
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp7
-rw-r--r--src/mongo/db/commands/geo_near_cmd.cpp15
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp14
-rw-r--r--src/mongo/db/commands/group_cmd.cpp4
-rw-r--r--src/mongo/db/commands/mr.cpp8
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp7
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp7
-rw-r--r--src/mongo/db/curop.cpp10
-rw-r--r--src/mongo/db/curop.h6
-rw-r--r--src/mongo/db/exec/update.cpp10
-rw-r--r--src/mongo/db/exec/update.h7
-rw-r--r--src/mongo/db/instance.cpp10
-rw-r--r--src/mongo/db/ops/update.cpp4
-rw-r--r--src/mongo/db/query/explain.cpp1
-rw-r--r--src/mongo/db/query/explain.h35
-rw-r--r--src/mongo/db/query/find.cpp20
-rw-r--r--src/mongo/db/query/plan_summary_stats.h68
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp1
20 files changed, 160 insertions, 82 deletions
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index b8367c35642..6f4d183adee 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/exec/count.h"
#include "mongo/db/query/explain.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/range_preserver.h"
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/util/log.h"
@@ -165,8 +166,7 @@ public:
if (collection) {
collection->infoCache()->notifyOfQuery(txn, summaryStats.indexesUsed);
}
- CurOp::get(txn)->debug().fromMultiPlanner = summaryStats.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = summaryStats.replanned;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(summaryStats);
// Plan is done executing. We just need to pull the count out of the root stage.
invariant(STAGE_COUNT == exec->getRootStage()->stageType());
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index 966a7d5b32b..16ea9564a64 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -48,6 +48,7 @@
#include "mongo/db/query/explain.h"
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_planner_common.h"
#include "mongo/util/log.h"
#include "mongo/util/timer.h"
@@ -234,8 +235,7 @@ public:
if (collection) {
collection->infoCache()->notifyOfQuery(txn, stats.indexesUsed);
}
- CurOp::get(txn)->debug().fromMultiPlanner = stats.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = stats.replanned;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(stats);
verify(start == bb.buf());
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index c806e67bdb7..2bc45997561 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -59,6 +59,7 @@
#include "mongo/db/query/find_and_modify_request.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/plan_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/db/s/collection_sharding_state.h"
@@ -404,8 +405,7 @@ public:
if (collection) {
collection->infoCache()->notifyOfQuery(txn, summaryStats.indexesUsed);
}
- CurOp::get(txn)->debug().fromMultiPlanner = summaryStats.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = summaryStats.replanned;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(summaryStats);
// Fill out OpDebug with the number of deleted docs.
CurOp::get(txn)->debug().ndeleted = getDeleteStats(exec.get())->docsDeleted;
@@ -494,7 +494,8 @@ public:
if (collection) {
collection->infoCache()->notifyOfQuery(txn, summaryStats.indexesUsed);
}
- UpdateStage::fillOutOpDebug(getUpdateStats(exec.get()), &summaryStats, opDebug);
+ UpdateStage::recordUpdateStatsInOpDebug(getUpdateStats(exec.get()), opDebug);
+ opDebug->setPlanSummaryMetrics(summaryStats);
boost::optional<BSONObj> value = advanceStatus.getValue();
appendCommandResponse(exec.get(), args.isRemove(), value, result);
diff --git a/src/mongo/db/commands/geo_near_cmd.cpp b/src/mongo/db/commands/geo_near_cmd.cpp
index 080903e2320..e431571b096 100644
--- a/src/mongo/db/commands/geo_near_cmd.cpp
+++ b/src/mongo/db/commands/geo_near_cmd.cpp
@@ -50,6 +50,7 @@
#include "mongo/db/query/explain.h"
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/range_preserver.h"
#include "mongo/platform/unordered_map.h"
#include "mongo/util/log.h"
@@ -280,15 +281,11 @@ public:
<< WorkingSetCommon::toStatusString(currObj)));
}
- // Fill out the stats subobj.
- BSONObjBuilder stats(result.subobjStart("stats"));
-
- // Fill in nscanned from the explain.
PlanSummaryStats summary;
Explain::getSummaryStats(*exec, &summary);
- collection->infoCache()->notifyOfQuery(txn, summary.indexesUsed);
- CurOp::get(txn)->debug().fromMultiPlanner = summary.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = summary.replanned;
+
+ // Fill out the stats subobj.
+ BSONObjBuilder stats(result.subobjStart("stats"));
stats.appendNumber("nscanned", summary.totalKeysExamined);
stats.appendNumber("objectsLoaded", summary.totalDocsExamined);
@@ -300,6 +297,10 @@ public:
stats.append("time", CurOp::get(txn)->elapsedMillis());
stats.done();
+ collection->infoCache()->notifyOfQuery(txn, summary.indexesUsed);
+
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(summary);
+
return true;
}
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 9b7e54b04ca..5ba50fe0dde 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -48,6 +48,7 @@
#include "mongo/db/query/find.h"
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/getmore_request.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/s/operation_sharding_state.h"
@@ -320,6 +321,13 @@ public:
BSONObj obj;
PlanExecutor::ExecState state;
long long numResults = 0;
+
+ // We report keysExamined and docsExamined to OpDebug for a given getMore operation. To
+ // obtain these values we need to take a diff of the pre-execution and post-execution
+ // metrics, as they accumulate over the course of a cursor's lifetime.
+ PlanSummaryStats preExecutionStats;
+ Explain::getSummaryStats(*exec, &preExecutionStats);
+
Status batchStatus = generateBatch(cursor, request, &nextBatch, &state, &numResults);
if (!batchStatus.isOK()) {
return appendCommandStatus(result, batchStatus);
@@ -364,6 +372,12 @@ public:
}
}
+ PlanSummaryStats postExecutionStats;
+ Explain::getSummaryStats(*exec, &postExecutionStats);
+ postExecutionStats.totalKeysExamined -= preExecutionStats.totalKeysExamined;
+ postExecutionStats.totalDocsExamined -= preExecutionStats.totalDocsExamined;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(postExecutionStats);
+
if (shouldSaveCursorGetMore(state, exec, isCursorTailable(cursor))) {
respondWithId = request.cursorid;
diff --git a/src/mongo/db/commands/group_cmd.cpp b/src/mongo/db/commands/group_cmd.cpp
index 25554261b69..60eeac1feb7 100644
--- a/src/mongo/db/commands/group_cmd.cpp
+++ b/src/mongo/db/commands/group_cmd.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
namespace mongo {
@@ -172,8 +173,7 @@ private:
if (coll) {
coll->infoCache()->notifyOfQuery(txn, summaryStats.indexesUsed);
}
- CurOp::get(txn)->debug().fromMultiPlanner = summaryStats.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = summaryStats.replanned;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(summaryStats);
invariant(STAGE_GROUP == planExecutor->getRootStage()->stageType());
GroupStage* groupStage = static_cast<GroupStage*>(planExecutor->getRootStage());
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 1f97cce86da..8f125382095 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -58,6 +58,7 @@
#include "mongo/db/ops/insert.h"
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/range_preserver.h"
#include "mongo/db/repl/replication_coordinator_global.h"
@@ -1508,11 +1509,14 @@ public:
// Record the indexes used by the PlanExecutor.
PlanSummaryStats stats;
Explain::getSummaryStats(*exec, &stats);
+
+ // TODO SERVER-23261: Confirm whether this is the correct place to gather all
+ // metrics. There is no harm adding here for the time being.
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(stats);
+
Collection* coll = scopedAutoDb->getDb()->getCollection(config.ns);
invariant(coll); // 'exec' hasn't been killed, so collection must be alive.
coll->infoCache()->notifyOfQuery(txn, stats.indexesUsed);
- CurOp::get(txn)->debug().fromMultiPlanner = stats.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = stats.replanned;
}
pm.finished();
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index d8836346c5e..ffe18cfb3cb 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -51,6 +51,7 @@
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/stdx/memory.h"
#include "mongo/util/scopeguard.h"
@@ -247,8 +248,10 @@ public:
PlanSummaryStats stats;
Explain::getSummaryStats(*input, &stats);
collection->infoCache()->notifyOfQuery(txn, stats.indexesUsed);
- CurOp::get(txn)->debug().fromMultiPlanner = stats.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = stats.replanned;
+
+ // TODO SERVER-23265: Confirm whether this is the correct place to gather all
+ // metrics. There is no harm adding here for the time being.
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(stats);
}
// Create the PlanExecutor which returns results from the pipeline. The WorkingSet
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index bd71a02d6aa..e20696f3394 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -58,6 +58,7 @@
#include "mongo/db/ops/update_lifecycle_impl.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/plan_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_knobs.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/repl_client_info.h"
@@ -1126,7 +1127,8 @@ static void multiUpdate(OperationContext* txn,
collection->infoCache()->notifyOfQuery(txn, summary.indexesUsed);
const UpdateStats* updateStats = UpdateStage::getUpdateStats(exec.get());
- UpdateStage::fillOutOpDebug(updateStats, &summary, debug);
+ UpdateStage::recordUpdateStatsInOpDebug(updateStats, debug);
+ debug->setPlanSummaryMetrics(summary);
UpdateResult res = UpdateStage::makeUpdateResult(updateStats);
@@ -1248,8 +1250,7 @@ static void multiRemove(OperationContext* txn,
if (collection) {
collection->infoCache()->notifyOfQuery(txn, summary.indexesUsed);
}
- CurOp::get(txn)->debug().fromMultiPlanner = summary.fromMultiPlanner;
- CurOp::get(txn)->debug().replanned = summary.replanned;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(summary);
if (repl::ReplClientInfo::forClient(client).getLastOp() != lastOpAtOperationStart) {
// If this operation has already generated a new lastOp, don't bother setting it
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp
index dc9f819dc73..6b8618b3843 100644
--- a/src/mongo/db/curop.cpp
+++ b/src/mongo/db/curop.cpp
@@ -40,6 +40,7 @@
#include "mongo/db/cursor_id.h"
#include "mongo/db/json.h"
#include "mongo/db/query/getmore_request.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/util/fail_point_service.h"
#include "mongo/util/log.h"
@@ -674,4 +675,13 @@ void OpDebug::append(const CurOp& curop,
execStats.append(b, "execStats");
}
+void OpDebug::setPlanSummaryMetrics(const PlanSummaryStats& planSummaryStats) {
+ keysExamined = planSummaryStats.totalKeysExamined;
+ docsExamined = planSummaryStats.totalDocsExamined;
+ idhack = planSummaryStats.isIdhack;
+ hasSortStage = planSummaryStats.hasSortStage;
+ fromMultiPlanner = planSummaryStats.fromMultiPlanner;
+ replanned = planSummaryStats.replanned;
+}
+
} // namespace mongo
diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h
index 2b79b888e0e..06539aeaacd 100644
--- a/src/mongo/db/curop.h
+++ b/src/mongo/db/curop.h
@@ -47,6 +47,7 @@ class Client;
class Command;
class CurOp;
class OperationContext;
+struct PlanSummaryStats;
/**
* stores a copy of a bson obj in a fixed size buffer
@@ -141,6 +142,11 @@ public:
const SingleThreadedLockStats& lockStats,
BSONObjBuilder& builder) const;
+ /**
+ * Copies relevant plan summary metrics to this OpDebug instance.
+ */
+ void setPlanSummaryMetrics(const PlanSummaryStats& planSummaryStats);
+
// -------------------
// basic options
diff --git a/src/mongo/db/exec/update.cpp b/src/mongo/db/exec/update.cpp
index d6118a1187e..1b52796a5a5 100644
--- a/src/mongo/db/exec/update.cpp
+++ b/src/mongo/db/exec/update.cpp
@@ -1031,20 +1031,12 @@ const UpdateStats* UpdateStage::getUpdateStats(const PlanExecutor* exec) {
return static_cast<const UpdateStats*>(updateStage->getSpecificStats());
}
-void UpdateStage::fillOutOpDebug(const UpdateStats* updateStats,
- const PlanSummaryStats* summaryStats,
- OpDebug* opDebug) {
+void UpdateStage::recordUpdateStatsInOpDebug(const UpdateStats* updateStats, OpDebug* opDebug) {
opDebug->nMatched = updateStats->nMatched;
opDebug->nModified = updateStats->nModified;
opDebug->upsert = updateStats->inserted;
opDebug->fastmodinsert = updateStats->fastmodinsert;
opDebug->fastmod = updateStats->fastmod;
-
- // Copy summary information about the plan into OpDebug.
- opDebug->keysExamined = summaryStats->totalKeysExamined;
- opDebug->docsExamined = summaryStats->totalDocsExamined;
- opDebug->fromMultiPlanner = summaryStats->fromMultiPlanner;
- opDebug->replanned = summaryStats->replanned;
}
UpdateResult UpdateStage::makeUpdateResult(const UpdateStats* updateStats) {
diff --git a/src/mongo/db/exec/update.h b/src/mongo/db/exec/update.h
index 0fa391c778f..c39717f9748 100644
--- a/src/mongo/db/exec/update.h
+++ b/src/mongo/db/exec/update.h
@@ -106,12 +106,9 @@ public:
static const UpdateStats* getUpdateStats(const PlanExecutor* exec);
/**
- * Populate 'opDebug' with stats from 'updateStats' and 'summaryStats' describing the execution
- * of this update.
+ * Populate 'opDebug' with stats from 'updateStats' describing the execution of this update.
*/
- static void fillOutOpDebug(const UpdateStats* updateStats,
- const PlanSummaryStats* summaryStats,
- OpDebug* opDebug);
+ static void recordUpdateStatsInOpDebug(const UpdateStats* updateStats, OpDebug* opDebug);
/**
* Converts 'updateStats' into an UpdateResult.
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 947f0485c2c..bce793e9c6c 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -76,6 +76,7 @@
#include "mongo/db/ops/update_request.h"
#include "mongo/db/query/find.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/repl/replication_coordinator_global.h"
@@ -730,7 +731,8 @@ void receivedUpdate(OperationContext* txn, const NamespaceString& nsString, Mess
}
const UpdateStats* updateStats = UpdateStage::getUpdateStats(exec.get());
- UpdateStage::fillOutOpDebug(updateStats, &summary, &op.debug());
+ UpdateStage::recordUpdateStatsInOpDebug(updateStats, &op.debug());
+ op.debug().setPlanSummaryMetrics(summary);
UpdateResult res = UpdateStage::makeUpdateResult(updateStats);
@@ -794,7 +796,8 @@ void receivedUpdate(OperationContext* txn, const NamespaceString& nsString, Mess
collection->infoCache()->notifyOfQuery(txn, summary.indexesUsed);
const UpdateStats* updateStats = UpdateStage::getUpdateStats(exec.get());
- UpdateStage::fillOutOpDebug(updateStats, &summary, &op.debug());
+ UpdateStage::recordUpdateStatsInOpDebug(updateStats, &op.debug());
+ op.debug().setPlanSummaryMetrics(summary);
UpdateResult res = UpdateStage::makeUpdateResult(updateStats);
@@ -875,8 +878,7 @@ void receivedDelete(OperationContext* txn, const NamespaceString& nsString, Mess
if (collection) {
collection->infoCache()->notifyOfQuery(txn, summary.indexesUsed);
}
- op.debug().fromMultiPlanner = summary.fromMultiPlanner;
- op.debug().replanned = summary.replanned;
+ CurOp::get(txn)->debug().setPlanSummaryMetrics(summary);
if (repl::ReplClientInfo::forClient(client).getLastOp() != lastOpAtOperationStart) {
// If this operation has already generated a new lastOp, don't bother setting it
diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp
index 94caffaed71..010abf6be3b 100644
--- a/src/mongo/db/ops/update.cpp
+++ b/src/mongo/db/ops/update.cpp
@@ -48,6 +48,7 @@
#include "mongo/db/ops/update_lifecycle.h"
#include "mongo/db/query/explain.h"
#include "mongo/db/query/get_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/db/update_index_data.h"
@@ -126,7 +127,8 @@ UpdateResult update(OperationContext* txn,
PlanSummaryStats summaryStats;
Explain::getSummaryStats(*exec, &summaryStats);
const UpdateStats* updateStats = UpdateStage::getUpdateStats(exec.get());
- UpdateStage::fillOutOpDebug(updateStats, &summaryStats, opDebug);
+ UpdateStage::recordUpdateStatsInOpDebug(updateStats, opDebug);
+ opDebug->setPlanSummaryMetrics(summaryStats);
return UpdateStage::makeUpdateResult(updateStats);
}
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp
index 890d50e9021..a1eb04332e3 100644
--- a/src/mongo/db/query/explain.cpp
+++ b/src/mongo/db/query/explain.cpp
@@ -41,6 +41,7 @@
#include "mongo/db/exec/text.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/plan_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_settings.h"
#include "mongo/db/query/stage_builder.h"
diff --git a/src/mongo/db/query/explain.h b/src/mongo/db/query/explain.h
index 21edf161597..95fc193cbb2 100644
--- a/src/mongo/db/query/explain.h
+++ b/src/mongo/db/query/explain.h
@@ -40,40 +40,7 @@ namespace mongo {
class Collection;
class OperationContext;
-
-/**
- * A container for the summary statistics that the profiler, slow query log, and
- * other non-explain debug mechanisms may want to collect.
- */
-struct PlanSummaryStats {
- // The number of results returned by the plan.
- size_t nReturned = 0U;
-
- // The total number of index keys examined by the plan.
- size_t totalKeysExamined = 0U;
-
- // The total number of documents examined by the plan.
- size_t totalDocsExamined = 0U;
-
- // The number of milliseconds spent inside the root stage's work() method.
- long long executionTimeMillis = 0;
-
- // Did this plan use the fast path for key-value retrievals on the _id index?
- bool isIdhack = false;
-
- // Did this plan use an in-memory sort stage?
- bool hasSortStage = false;
-
- // The names of each index used by the plan.
- std::set<std::string> indexesUsed;
-
- // Was this plan a result of using the MultiPlanStage to select a winner among several
- // candidates?
- bool fromMultiPlanner = false;
-
- // Was a replan triggered during the execution of this query?
- bool replanned = false;
-};
+struct PlanSummaryStats;
/**
* Namespace for the collection of static methods used to generate explain information.
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index edc77d515bf..c54be93d0e5 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -49,6 +49,7 @@
#include "mongo/db/query/find_common.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/internal_plans.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_planner_params.h"
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/db/s/collection_sharding_state.h"
@@ -153,12 +154,7 @@ void endQueryOp(OperationContext* txn,
// Fill out curop based on explain summary statistics.
PlanSummaryStats summaryStats;
Explain::getSummaryStats(exec, &summaryStats);
- curop->debug().hasSortStage = summaryStats.hasSortStage;
- curop->debug().keysExamined = summaryStats.totalKeysExamined;
- curop->debug().docsExamined = summaryStats.totalDocsExamined;
- curop->debug().idhack = summaryStats.isIdhack;
- curop->debug().fromMultiPlanner = summaryStats.fromMultiPlanner;
- curop->debug().replanned = summaryStats.replanned;
+ curop->debug().setPlanSummaryMetrics(summaryStats);
if (collection) {
collection->infoCache()->notifyOfQuery(txn, summaryStats.indexesUsed);
@@ -393,6 +389,12 @@ QueryResult::View getMore(OperationContext* txn,
exec->restoreState();
PlanExecutor::ExecState state;
+ // We report keysExamined and docsExamined to OpDebug for a given getMore operation. To
+ // obtain these values we need to take a diff of the pre-execution and post-execution
+ // metrics, as they accumulate over the course of a cursor's lifetime.
+ PlanSummaryStats preExecutionStats;
+ Explain::getSummaryStats(*exec, &preExecutionStats);
+
generateBatch(ntoreturn, cc, &bb, &numResults, &slaveReadTill, &state);
// If this is an await data cursor, and we hit EOF without generating any results, then
@@ -420,6 +422,12 @@ QueryResult::View getMore(OperationContext* txn,
generateBatch(ntoreturn, cc, &bb, &numResults, &slaveReadTill, &state);
}
+ PlanSummaryStats postExecutionStats;
+ Explain::getSummaryStats(*exec, &postExecutionStats);
+ postExecutionStats.totalKeysExamined -= preExecutionStats.totalKeysExamined;
+ postExecutionStats.totalDocsExamined -= preExecutionStats.totalDocsExamined;
+ curop.debug().setPlanSummaryMetrics(postExecutionStats);
+
// We have to do this before re-acquiring locks in the agg case because
// shouldSaveCursorGetMore() can make a network call for agg cursors.
//
diff --git a/src/mongo/db/query/plan_summary_stats.h b/src/mongo/db/query/plan_summary_stats.h
new file mode 100644
index 00000000000..8168ea9f401
--- /dev/null
+++ b/src/mongo/db/query/plan_summary_stats.h
@@ -0,0 +1,68 @@
+/* Copyright 2016 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace mongo {
+
+/**
+ * A container for the summary statistics that the profiler, slow query log, and
+ * other non-explain debug mechanisms may want to collect.
+ */
+struct PlanSummaryStats {
+ // The number of results returned by the plan.
+ size_t nReturned = 0U;
+
+ // The total number of index keys examined by the plan.
+ size_t totalKeysExamined = 0U;
+
+ // The total number of documents examined by the plan.
+ size_t totalDocsExamined = 0U;
+
+ // The number of milliseconds spent inside the root stage's work() method.
+ long long executionTimeMillis = 0;
+
+ // Did this plan use the fast path for key-value retrievals on the _id index?
+ bool isIdhack = false;
+
+ // Did this plan use an in-memory sort stage?
+ bool hasSortStage = false;
+
+ // The names of each index used by the plan.
+ std::set<std::string> indexesUsed;
+
+ // Was this plan a result of using the MultiPlanStage to select a winner among several
+ // candidates?
+ bool fromMultiPlanner = false;
+
+ // Was a replan triggered during the execution of this query?
+ bool replanned = false;
+};
+
+} // namespace mongo
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index a26a657d4b5..4056c439545 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -44,6 +44,7 @@
#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/plan_executor.h"
+#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_knobs.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_planner_test_lib.h"