From 0f1cf1b71a12d2e41aeea064848ef192bfceddd7 Mon Sep 17 00:00:00 2001 From: James Wahlin Date: Wed, 6 Apr 2016 14:45:29 -0400 Subject: SERVER-23257 Report keysExamined/docsExamined/hasSortStage where valid --- src/mongo/db/query/explain.cpp | 1 + src/mongo/db/query/explain.h | 35 +---------------- src/mongo/db/query/find.cpp | 20 +++++++--- src/mongo/db/query/plan_summary_stats.h | 68 +++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 40 deletions(-) create mode 100644 src/mongo/db/query/plan_summary_stats.h (limited to 'src/mongo/db/query') 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 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 . + * + * 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 + +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 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 -- cgit v1.2.1