diff options
author | Haley Connelly <haley.connelly@10gen.com> | 2018-08-13 10:15:38 -0400 |
---|---|---|
committer | Haley Connelly <haley.connelly@10gen.com> | 2018-08-13 10:16:22 -0400 |
commit | 1ce4c3db9f598a5c0988362a6908d9b83c07e94f (patch) | |
tree | 65f8dd10a32230218423f87adc5f10b79cf5b31c /src/mongo | |
parent | ec6f2a54d8b901e95e556d53647944be8ce441d5 (diff) | |
download | mongo-1ce4c3db9f598a5c0988362a6908d9b83c07e94f.tar.gz |
SERVER-35980 Experimental new output format for planCacheListPlans
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/plan_cache_commands.cpp | 79 | ||||
-rw-r--r-- | src/mongo/db/query/explain.h | 34 | ||||
-rw-r--r-- | src/mongo/db/query/query_knobs.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/query_knobs.h | 3 |
4 files changed, 79 insertions, 39 deletions
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp index 3c1d6a00a6a..15616a20cf8 100644 --- a/src/mongo/db/commands/plan_cache_commands.cpp +++ b/src/mongo/db/commands/plan_cache_commands.cpp @@ -357,30 +357,15 @@ Status PlanCacheListPlans::runPlanCacheCommand(OperationContext* opCtx, AutoGetCollectionForReadCommand ctx(opCtx, NamespaceString(ns)); PlanCache* planCache; - Status status = getPlanCache(opCtx, ctx.getCollection(), ns, &planCache); - if (!status.isOK()) { - // No collection - return empty plans array. - BSONArrayBuilder plansBuilder(bob->subarrayStart("plans")); - plansBuilder.doneFast(); - return Status::OK(); - } + uassertStatusOK(getPlanCache(opCtx, ctx.getCollection(), ns, &planCache)); return list(opCtx, *planCache, ns, cmdObj, bob); } -// static -Status PlanCacheListPlans::list(OperationContext* opCtx, - const PlanCache& planCache, - const std::string& ns, - const BSONObj& cmdObj, - BSONObjBuilder* bob) { - auto statusWithCQ = canonicalize(opCtx, ns, cmdObj); - if (!statusWithCQ.isOK()) { - return statusWithCQ.getStatus(); - } - unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); - +namespace { +Status listPlansOriginalFormat(std::unique_ptr<CanonicalQuery> cq, + const PlanCache& planCache, + BSONObjBuilder* bob) { auto lookupResult = planCache.getEntry(*cq); - if (lookupResult == ErrorCodes::NoSuchKey) { // Return empty plans in results if query shape does not // exist in plan cache. @@ -390,9 +375,11 @@ Status PlanCacheListPlans::list(OperationContext* opCtx, } else if (!lookupResult.isOK()) { return lookupResult.getStatus(); } - std::unique_ptr<PlanCacheEntry> entry = std::move(lookupResult.getValue()); + + auto entry = std::move(lookupResult.getValue()); BSONArrayBuilder plansBuilder(bob->subarrayStart("plans")); + size_t numPlans = entry->plannerData.size(); invariant(numPlans == entry->decision->stats.size()); invariant(numPlans == entry->decision->scores.size()); @@ -442,7 +429,57 @@ Status PlanCacheListPlans::list(OperationContext* opCtx, // Append whether or not the entry is active. bob->append("isActive", entry->isActive); bob->append("works", static_cast<long long>(entry->works)); + return Status::OK(); +} +} // namespace +// static +Status PlanCacheListPlans::list(OperationContext* opCtx, + const PlanCache& planCache, + const std::string& ns, + const BSONObj& cmdObj, + BSONObjBuilder* bob) { + auto statusWithCQ = canonicalize(opCtx, ns, cmdObj); + if (!statusWithCQ.isOK()) { + return statusWithCQ.getStatus(); + } + + if (!internalQueryCacheListPlansNewOutput.load()) + return listPlansOriginalFormat(std::move(statusWithCQ.getValue()), planCache, bob); + + unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); + auto entry = uassertStatusOK(planCache.getEntry(*cq)); + + // internalQueryCacheDisableInactiveEntries is True and we should use the new output format. + BSONObjBuilder shapeBuilder(bob->subobjStart("createdFromQuery")); + shapeBuilder.append("query", entry->query); + shapeBuilder.append("sort", entry->sort); + shapeBuilder.append("projection", entry->projection); + if (!entry->collation.isEmpty()) { + shapeBuilder.append("collation", entry->collation); + } + shapeBuilder.doneFast(); + bob->append("queryHash", unsignedIntToFixedLengthHex(entry->queryHash)); + + // Append whether or not the entry is active. + bob->append("isActive", entry->isActive); + bob->append("works", static_cast<long long>(entry->works)); + + BSONObjBuilder cachedPlanBob(bob->subobjStart("cachedPlan")); + Explain::statsToBSON( + *entry->decision->stats[0], &cachedPlanBob, ExplainOptions::Verbosity::kQueryPlanner); + cachedPlanBob.doneFast(); + + bob->append("timeOfCreation", entry->timeOfCreation); + + BSONArrayBuilder creationBuilder(bob->subarrayStart("creationExecStats")); + for (auto&& stat : entry->decision->stats) { + BSONObjBuilder planBob(creationBuilder.subobjStart()); + Explain::generateSinglePlanExecutionInfo( + stat.get(), ExplainOptions::Verbosity::kExecAllPlans, boost::none, &planBob); + planBob.doneFast(); + } + creationBuilder.doneFast(); return Status::OK(); } diff --git a/src/mongo/db/query/explain.h b/src/mongo/db/query/explain.h index cb177321f1c..451ffabe219 100644 --- a/src/mongo/db/query/explain.h +++ b/src/mongo/db/query/explain.h @@ -164,6 +164,22 @@ public: **/ static std::unique_ptr<PlanStageStats> getWinningPlanTrialStats(PlanExecutor* exec); + /** + * Generates the execution stats section for the stats tree 'stats', adding the resulting BSON + * to 'out'. + * + * The 'totalTimeMillis' value passed here will be added to the top level of the execution stats + * section, but will not affect the reporting of timing for individual stages. If + * 'totalTimeMillis' is not set, we use the approximate timing information collected by the + * stages. + * + * Stats are generated at the verbosity specified by 'verbosity'. + **/ + static void generateSinglePlanExecutionInfo(const PlanStageStats* stats, + ExplainOptions::Verbosity verbosity, + boost::optional<long long> totalTimeMillis, + BSONObjBuilder* out); + private: /** * Adds the 'queryPlanner' explain section to the BSON object being built @@ -207,24 +223,6 @@ private: BSONObjBuilder* out); /** - * Generates the execution stats section for the stats tree 'stats', - * adding the resulting BSON to 'out'. - * - * The 'totalTimeMillis' value passed here will be added to the top level of - * the execution stats section, but will not affect the reporting of timing for - * individual stages. If 'totalTimeMillis' is not set, we use the approximate timing - * information collected by the stages. - * - * Stats are generated at the verbosity specified by 'verbosity'. - * - * This is a helper for generating explain BSON. It is used by generateExecutionInfo(). - */ - static void generateSinglePlanExecutionInfo(const PlanStageStats* stats, - ExplainOptions::Verbosity verbosity, - boost::optional<long long> totalTimeMillis, - BSONObjBuilder* out); - - /** * Adds the 'serverInfo' explain section to the BSON object being build * by 'out'. * diff --git a/src/mongo/db/query/query_knobs.cpp b/src/mongo/db/query/query_knobs.cpp index 3f002ddf784..4d59a177c2e 100644 --- a/src/mongo/db/query/query_knobs.cpp +++ b/src/mongo/db/query/query_knobs.cpp @@ -55,6 +55,8 @@ MONGO_EXPORT_SERVER_PARAMETER(internalQueryCacheWorksGrowthCoefficient, double, MONGO_EXPORT_SERVER_PARAMETER(internalQueryCacheDisableInactiveEntries, bool, false); +MONGO_EXPORT_SERVER_PARAMETER(internalQueryCacheListPlansNewOutput, bool, false); + MONGO_EXPORT_SERVER_PARAMETER(internalQueryPlannerMaxIndexedSolutions, int, 64); MONGO_EXPORT_SERVER_PARAMETER(internalQueryEnumerationMaxOrSolutions, int, 10); diff --git a/src/mongo/db/query/query_knobs.h b/src/mongo/db/query/query_knobs.h index b0c6849b2ea..d7f6ab8d1c4 100644 --- a/src/mongo/db/query/query_knobs.h +++ b/src/mongo/db/query/query_knobs.h @@ -79,6 +79,9 @@ extern AtomicDouble internalQueryCacheWorksGrowthCoefficient; // Whether or not cache entries can be marked as "inactive." extern AtomicBool internalQueryCacheDisableInactiveEntries; +// Whether or not planCacheListPlans uses the new output format. +extern AtomicBool internalQueryCacheListPlansNewOutput; + // // Planning and enumeration. // |