diff options
author | samontea <merciers.merciers@gmail.com> | 2019-05-31 14:05:37 -0400 |
---|---|---|
committer | samontea <merciers.merciers@gmail.com> | 2019-07-10 16:07:42 -0400 |
commit | 6bba6446e632b557ccc03834d4d48e90336679fc (patch) | |
tree | 8f550393c99b15f4b27d9bbb27115fc451930be7 /src/mongo/db/exec/multi_plan.cpp | |
parent | 0434f018920206c197ab06b96e1a74dcbdf8885a (diff) | |
download | mongo-6bba6446e632b557ccc03834d4d48e90336679fc.tar.gz |
SERVER-41279 Eliminate failed plans from consideration during query planning
Diffstat (limited to 'src/mongo/db/exec/multi_plan.cpp')
-rw-r--r-- | src/mongo/db/exec/multi_plan.cpp | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp index fa5a3ded422..9cb692efa55 100644 --- a/src/mongo/db/exec/multi_plan.cpp +++ b/src/mongo/db/exec/multi_plan.cpp @@ -219,13 +219,23 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { // After picking best plan, ranking will own plan stats from // candidate solutions (winner and losers). - std::unique_ptr<PlanRankingDecision> ranking(new PlanRankingDecision); - _bestPlanIdx = PlanRanker::pickBestPlan(_candidates, ranking.get()); + auto statusWithRanking = PlanRanker::pickBestPlan(_candidates); + if (!statusWithRanking.isOK()) { + return statusWithRanking.getStatus(); + } + + auto ranking = std::move(statusWithRanking.getValue()); + // Since the status was ok there should be a ranking containing at least one successfully ranked + // plan. + invariant(ranking); + _bestPlanIdx = ranking->candidateOrder[0]; + verify(_bestPlanIdx >= 0 && _bestPlanIdx < static_cast<int>(_candidates.size())); - // Copy candidate order. We will need this to sort candidate stats for explain - // after transferring ownership of 'ranking' to plan cache. + // Copy candidate order and failed candidates. We will need this to sort candidate stats for + // explain after transferring ownership of 'ranking' to plan cache. std::vector<size_t> candidateOrder = ranking->candidateOrder; + std::vector<size_t> failedCandidates = ranking->failedCandidates; CandidatePlan& bestCandidate = _candidates[_bestPlanIdx]; const auto& alreadyProduced = bestCandidate.results; @@ -237,7 +247,7 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { _backupPlanIdx = kNoSuchPlan; if (bestSolution->hasBlockingStage && (0 == alreadyProduced.size())) { LOG(5) << "Winner has blocking stage, looking for backup plan..."; - for (size_t ix = 0; ix < _candidates.size(); ++ix) { + for (auto&& ix : candidateOrder) { if (!_candidates[ix].solution->hasBlockingStage) { LOG(5) << "Candidate " << ix << " is backup child"; _backupPlanIdx = ix; @@ -296,9 +306,11 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { std::vector<QuerySolution*> solutions; // Generate solutions and ranking decisions sorted by score. - for (size_t orderingIndex = 0; orderingIndex < candidateOrder.size(); ++orderingIndex) { - // index into candidates/ranking - size_t ix = candidateOrder[orderingIndex]; + for (auto&& ix : candidateOrder) { + solutions.push_back(_candidates[ix].solution.get()); + } + // Insert the failed plans in the back. + for (auto&& ix : failedCandidates) { solutions.push_back(_candidates[ix].solution.get()); } |