From 4381f26509152b62d95ee52898b81478466853c0 Mon Sep 17 00:00:00 2001 From: "3058078489@qq.com" <3058078489@qq.com> Date: Thu, 15 Jun 2023 14:19:27 +0800 Subject: [PATCH] not cache meaningless plan(advanced = 0 && works == 1 && isEOF == true) --- src/mongo/db/exec/plan_cache_util.cpp | 10 +++++++ src/mongo/db/exec/plan_cache_util.h | 39 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/mongo/db/exec/plan_cache_util.cpp b/src/mongo/db/exec/plan_cache_util.cpp index 0b40c4319219a..f4a7a9d210745 100644 --- a/src/mongo/db/exec/plan_cache_util.cpp +++ b/src/mongo/db/exec/plan_cache_util.cpp @@ -68,5 +68,15 @@ void logNotCachingNoData(std::string&& solution) { "Not caching query because this solution has no cache data", "solutions"_attr = redact(solution)); } + +void logNotCachingOneWorkesAndZeroResults(std::string&& query, double score, std::string winnerPlanSummary) { + LOGV2_DEBUG(20570, + 1, + "Winning plan had zero results, and only one work, skip caching", + "query"_attr = redact(query), + "winnerScore"_attr = score, + "winnerPlanSummary"_attr = winnerPlanSummary); + +} } // namespace log_detail } // namespace mongo::plan_cache_util diff --git a/src/mongo/db/exec/plan_cache_util.h b/src/mongo/db/exec/plan_cache_util.h index 8f0260409d7a8..052500034354d 100644 --- a/src/mongo/db/exec/plan_cache_util.h +++ b/src/mongo/db/exec/plan_cache_util.h @@ -67,6 +67,7 @@ void logTieForBest(std::string&& query, std::string runnerUpPlanSummary); void logNotCachingZeroResults(std::string&& query, double score, std::string winnerPlanSummary); void logNotCachingNoData(std::string&& solution); +void logNotCachingOneWorkesAndZeroResults(std::string&& query, double score, std::string winnerPlanSummary); } // namespace log_detail /** @@ -154,6 +155,44 @@ void updatePlanCache( } } + // when the mode is PlanCachingMode::AlwaysCache or PlanCachingMode::SometimesCache, there is a special case. + // take Classic plan cache for example: + // If the winning index's advanced = 0 && works == 1 && isEOF == true, which means we didn't get any data to rank score, all candidates + // score is same. the score of the calculation is meaningless. + // + //In this case, if we cache the plan, it will increased memory overhead. when the cached plan stage pick best plan, + //it will trigger replan. this will increase computing overhead. + if (canCache == true) { + std::unique_ptr winnerExplainer; + if constexpr (std::is_same_v>) { + winnerExplainer = plan_explainer_factory::make(candidates[winnerIdx].root.get(), + &candidates[winnerIdx].data, + candidates[winnerIdx].solution.get()); + auto const& rankingStats = ranking->getStats(); + auto numReads = calculateNumberOfReads(rankingStats.candidatePlanStats[winnerIdx].get()); + + if (numReads == 1 && rankingStats.candidatePlanStats[winnerIdx]->common.advances == 0 + && rankingStats.candidatePlanStats[winnerIdx]->common.isEOF == true) { + canCache = false; + log_detail::logNotCachingOneWorkesAndZeroResults( + query.toStringShort(), ranking->scores[0], winnerExplainer->getPlanSummary()); + } + } else { + static_assert(std::is_same_v); + winnerExplainer = plan_explainer_factory::make(candidates[winnerIdx].root); + + std::unique_ptr bestCandidateStatTrees; + bestCandidateStatTrees = candidates[winnerIdx].root->getStats(); + if (bestCandidateStatTrees->common.advanced == 0 + && bestCandidateStatTrees->common.works== 1 + && bestCandidateStatTrees->common.isEOF == true) { + canCache = false; + log_detail::logNotCachingOneWorkesAndZeroResults( + query.toStringShort(), ranking->scores[0], winnerExplainer->getPlanSummary()); + } + } + } + // Store the choice we just made in the cache, if the query is of a type that is safe to // cache. if (PlanCache::shouldCacheQuery(query) && canCache) {