diff options
Diffstat (limited to 'src/mongo/db/query/plan_cache.h')
-rw-r--r-- | src/mongo/db/query/plan_cache.h | 149 |
1 files changed, 87 insertions, 62 deletions
diff --git a/src/mongo/db/query/plan_cache.h b/src/mongo/db/query/plan_cache.h index e1e529d198f..b57fa2015b6 100644 --- a/src/mongo/db/query/plan_cache.h +++ b/src/mongo/db/query/plan_cache.h @@ -39,6 +39,7 @@ #include "mongo/db/query/index_tag.h" #include "mongo/db/query/lru_key_value.h" #include "mongo/db/query/plan_cache_indexability.h" +#include "mongo/db/query/plan_ranking_decision.h" #include "mongo/db/query/query_planner_params.h" #include "mongo/platform/atomic_word.h" #include "mongo/stdx/mutex.h" @@ -49,7 +50,6 @@ namespace mongo { // A PlanCacheKey is a string-ified version of a query's predicate/projection/sort. typedef std::string PlanCacheKey; -struct PlanRankingDecision; struct QuerySolution; struct QuerySolutionNode; @@ -58,16 +58,23 @@ struct QuerySolutionNode; * feedback is available to anyone who retrieves that query in the future. */ struct PlanCacheEntryFeedback { + uint64_t estimateObjectSizeInBytes() const { + return stats->estimateObjectSizeInBytes() + sizeof(*this); + } + + std::unique_ptr<PlanCacheEntryFeedback> clone() const { + auto clonedFeedback = stdx::make_unique<PlanCacheEntryFeedback>(); + clonedFeedback->stats.reset(stats->clone()); + clonedFeedback->score = score; + return clonedFeedback; + } + // How well did the cached plan perform? std::unique_ptr<PlanStageStats> stats; // The "goodness" score produced by the plan ranker // corresponding to 'stats'. double score; - - uint64_t estimateObjectSizeInBytes() const { - return stats->estimateObjectSizeInBytes() + sizeof(*this); - } }; // TODO: Replace with opaque type. @@ -185,8 +192,7 @@ struct SolutionCacheData { wholeIXSolnDir(1), indexFilterApplied(false) {} - // Make a deep copy. - SolutionCacheData* clone() const; + std::unique_ptr<SolutionCacheData> clone() const; // For debugging. std::string toString() const; @@ -234,28 +240,12 @@ private: MONGO_DISALLOW_COPYING(CachedSolution); public: - CachedSolution(const PlanCacheKey& key, const PlanCacheEntry& entry); - ~CachedSolution(); + CachedSolution(const PlanCacheEntry& entry); - // Owned here. - std::vector<SolutionCacheData*> plannerData; - - // Key used to provide feedback on the entry. - PlanCacheKey key; - - // For debugging. - std::string toString() const; + // Information that can be used by the QueryPlanner to reconstitute the complete execution plan. + std::unique_ptr<SolutionCacheData> plannerData; - // We are extracting just enough information from the canonical - // query. We could clone the canonical query but the following - // items are all that is displayed to the user. - BSONObj query; - BSONObj sort; - BSONObj projection; - BSONObj collation; - - // The number of work cycles taken to decide on a winning plan when the plan was first - // cached. + // The number of work cycles taken to decide on a winning plan when the plan was first cached. size_t decisionWorks; }; @@ -269,6 +259,54 @@ private: public: /** + * A description of the query from which a 'PlanCacheEntry' was created. + */ + struct CreatedFromQuery { + /** + * Returns an estimate of the size of this object, including the memory allocated elsewhere + * that it owns, in bytes. + */ + uint64_t estimateObjectSizeInBytes() const; + + std::string debugString() const; + + BSONObj filter; + BSONObj sort; + BSONObj projection; + BSONObj collation; + }; + + /** + * Per-plan cache entry information that is used strictly as debug information (e.g. is intended + * for display by the 'planCacheListPlans' command). In order to save memory, this information + * is sometimes discarded instead of kept in the plan cache entry. Therefore, this information + * may not be used for any purpose outside displaying debug info, such as recovering a plan from + * the cache or determining whether or not the cache entry is active. + */ + struct DebugInfo { + DebugInfo(CreatedFromQuery createdFromQuery, + std::unique_ptr<const PlanRankingDecision> decision, + std::vector<std::unique_ptr<PlanCacheEntryFeedback>> feedback); + + /** + * Returns an estimate of the size of this object, including the memory allocated elsewhere + * that it owns, in bytes. + */ + uint64_t estimateObjectSizeInBytes() const; + + std::unique_ptr<DebugInfo> clone() const; + + CreatedFromQuery createdFromQuery; + + // Information that went into picking the winning plan and also why the other plans lost. + // Never nullptr. + std::unique_ptr<const PlanRankingDecision> decision; + + // Scores from uses of this cache entry. + std::vector<std::unique_ptr<PlanCacheEntryFeedback>> feedback; + }; + + /** * Create a new PlanCacheEntry. * Grabs any planner-specific data required from the solutions. */ @@ -285,39 +323,34 @@ public: */ PlanCacheEntry* clone() const; - // For debugging. - std::string toString() const; + std::string debugString() const; + // Data provided to the planner to allow it to recreate the solution this entry represents. In + // order to return it from the cache for consumption by the 'QueryPlanner', a deep copy is made + // and returned inside 'CachedSolution'. // - // Planner data - // - - // Data provided to the planner to allow it to recreate the solutions this entry - // represents. Each SolutionCacheData is fully owned here, so in order to return - // it from the cache a deep copy is made and returned inside CachedSolution. + // The first element of the vector is the cache data associated with the winning plan. The + // remaining elements correspond to the rejected plans, sorted by descending score. const std::vector<std::unique_ptr<const SolutionCacheData>> plannerData; - // TODO: Do we really want to just hold a copy of the CanonicalQuery? For now we just - // extract the data we need. - // - // Used by the plan cache commands to display an example query - // of the appropriate shape. - const BSONObj query; - const BSONObj sort; - const BSONObj projection; - const BSONObj collation; const Date_t timeOfCreation; - // - // Performance stats - // + // The number of work taken to select the winning plan when this plan cache entry was first + // created. + const size_t decisionWorks; - // Information that went into picking the winning plan and also why the other plans lost. - const std::unique_ptr<const PlanRankingDecision> decision; + // Optional debug info containing detailed statistics. Includes a description of the query which + // resulted in this plan cache's creation as well as runtime stats from the multi-planner trial + // period that resulted in this cache entry. + // + // Once the estimated cumulative size of the mongod's plan caches exceeds a threshold, this + // debug info is omitted from new plan cache entries. + std::unique_ptr<DebugInfo> debugInfo; - // Annotations from cached runs. The CachedPlanStage provides these stats about its - // runs when they complete. - std::vector<PlanCacheEntryFeedback*> feedback; + // An estimate of the size in bytes of this plan cache entry. This is the "deep size", + // calculated by recursively incorporating the size of owned objects, the objects that they in + // turn own, and so on. + const uint64_t estimatedEntrySizeBytes; /** * Tracks the approximate cumulative size of the plan cache entries across all the collections. @@ -329,19 +362,11 @@ private: * All arguments constructor. */ PlanCacheEntry(std::vector<std::unique_ptr<const SolutionCacheData>> plannerData, - const BSONObj& query, - const BSONObj& sort, - const BSONObj& projection, - const BSONObj& collation, Date_t timeOfCreation, - std::unique_ptr<const PlanRankingDecision> decision, - std::vector<PlanCacheEntryFeedback*> feedback); + size_t decisionWorks, + std::unique_ptr<DebugInfo> debugInfo); uint64_t _estimateObjectSizeInBytes() const; - - // The total runtime size of the current object in bytes. This is the deep size, obtained by - // recursively following references to all owned objects. - const uint64_t _entireObjectSize; }; /** |