diff options
author | Ivan Fefer <ivan.fefer@mongodb.com> | 2022-09-29 07:03:14 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-09-29 07:38:52 +0000 |
commit | 1d93d09948c29534f7c82950ba7771ac0f4da22c (patch) | |
tree | c32d27d465afbcd0bbe23a378494bad81ac8286d /src/mongo/db/exec/multi_plan.cpp | |
parent | 1990f6a8a6cab84e2ddd05ab0469b9481b962ed5 (diff) | |
download | mongo-1d93d09948c29534f7c82950ba7771ac0f4da22c.tar.gz |
SERVER-58712: Fix update performance on collections with multiple secondary indexes on same key
Diffstat (limited to 'src/mongo/db/exec/multi_plan.cpp')
-rw-r--r-- | src/mongo/db/exec/multi_plan.cpp | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp index 0f2ff61ac66..cff149dd182 100644 --- a/src/mongo/db/exec/multi_plan.cpp +++ b/src/mongo/db/exec/multi_plan.cpp @@ -170,14 +170,13 @@ PlanStage::StageState MultiPlanStage::doWork(WorkingSetID* out) { .getPlanCache() ->remove(plan_cache_key_factory::make<PlanCacheKey>(*_query, collection())); - _bestPlanIdx = _backupPlanIdx; - _backupPlanIdx = kNoSuchPlan; + switchToBackupPlan(); return _candidates[_bestPlanIdx].root->work(out); } if (hasBackupPlan() && PlanStage::ADVANCED == state) { LOGV2_DEBUG(20589, 5, "Best plan had a blocking stage, became unblocked"); - _backupPlanIdx = kNoSuchPlan; + removeBackupPlan(); } return state; @@ -277,6 +276,7 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { *_query, std::move(ranking), _candidates); + removeRejectedPlans(); return Status::OK(); } @@ -352,6 +352,54 @@ bool MultiPlanStage::workAllPlans(size_t numResults, PlanYieldPolicy* yieldPolic return !doneWorking; } +void MultiPlanStage::removeRejectedPlans() { + // Move the best plan and the backup plan to the front of 'children'. + if (_bestPlanIdx != 0) { + std::swap(_children[_bestPlanIdx], _children[0]); + std::swap(_candidates[_bestPlanIdx], _candidates[0]); + if (_backupPlanIdx == 0) { + _backupPlanIdx = _bestPlanIdx; + } + _bestPlanIdx = 0; + } + size_t startIndex = 1; + if (_backupPlanIdx != kNoSuchPlan) { + if (_bestPlanIdx != 1) { + std::swap(_children[_backupPlanIdx], _children[1]); + std::swap(_candidates[_backupPlanIdx], _candidates[1]); + _backupPlanIdx = 1; + } + startIndex = 2; + } + + _rejected.reserve(_children.size() - startIndex); + for (size_t i = startIndex; i < _children.size(); ++i) { + rejectPlan(i); + } + _children.resize(startIndex); +} + +void MultiPlanStage::switchToBackupPlan() { + std::swap(_children[_backupPlanIdx], _children[_bestPlanIdx]); + std::swap(_candidates[_backupPlanIdx], _candidates[_bestPlanIdx]); + removeBackupPlan(); +} + +void MultiPlanStage::rejectPlan(size_t planIdx) { + auto rejectedPlan = std::move(_children[planIdx]); + if (opCtx() != nullptr) { + rejectedPlan->saveState(); + rejectedPlan->detachFromOperationContext(); + } + _rejected.emplace_back(std::move(rejectedPlan)); +} + +void MultiPlanStage::removeBackupPlan() { + rejectPlan(_backupPlanIdx); + _children.resize(1); + _backupPlanIdx = kNoSuchPlan; +} + bool MultiPlanStage::hasBackupPlan() const { return kNoSuchPlan != _backupPlanIdx; } @@ -386,6 +434,9 @@ unique_ptr<PlanStageStats> MultiPlanStage::getStats() { for (auto&& child : _children) { ret->children.emplace_back(child->getStats()); } + for (auto&& child : _rejected) { + ret->children.emplace_back(child->getStats()); + } return ret; } |