diff options
author | James Wahlin <james.wahlin@10gen.com> | 2016-04-06 14:45:29 -0400 |
---|---|---|
committer | James Wahlin <james.wahlin@10gen.com> | 2016-04-20 13:22:35 -0400 |
commit | 0f1cf1b71a12d2e41aeea064848ef192bfceddd7 (patch) | |
tree | a563d427ab4126a5fb05834f1d9dc9e6c0ed7ae6 /src/mongo | |
parent | 5dd37d3fa197e73fab8298e5d748e06393b053b2 (diff) | |
download | mongo-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.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/commands/distinct.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/commands/find_and_modify.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/commands/geo_near_cmd.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/commands/getmore_cmd.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/commands/group_cmd.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/commands/mr.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/commands/pipeline_command.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/batch_executor.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/curop.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/curop.h | 6 | ||||
-rw-r--r-- | src/mongo/db/exec/update.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/exec/update.h | 7 | ||||
-rw-r--r-- | src/mongo/db/instance.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/ops/update.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/query/explain.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/query/explain.h | 35 | ||||
-rw-r--r-- | src/mongo/db/query/find.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/query/plan_summary_stats.h | 68 | ||||
-rw-r--r-- | src/mongo/dbtests/query_stage_multiplan.cpp | 1 |
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" |