diff options
Diffstat (limited to 'src/mongo/db/query/get_executor.cpp')
| -rw-r--r-- | src/mongo/db/query/get_executor.cpp | 97 |
1 files changed, 37 insertions, 60 deletions
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index 602be15dbc2..db04d6a276a 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -29,13 +29,10 @@ #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery -#include "mongo/db/curop.h" #include "mongo/platform/basic.h" #include "mongo/db/query/get_executor.h" -#include "mongo/util/duration.h" -#include "mongo/util/tick_source.h" #include <boost/optional.hpp> #include <limits> #include <memory> @@ -110,7 +107,6 @@ #include "mongo/logv2/log.h" #include "mongo/scripting/engine.h" #include "mongo/util/str.h" -#include "mongo/util/timer.h" namespace mongo { MONGO_FAIL_POINT_DEFINE(includeFakeColumnarIndex); @@ -220,15 +216,10 @@ IndexEntry indexEntryFromIndexCatalogEntry(OperationContext* opCtx, MultikeyMetadataAccessStats mkAccessStats; if (canonicalQuery) { - RelevantFieldIndexMap fieldIndexProps; - QueryPlannerIXSelect::getFields(canonicalQuery->root(), &fieldIndexProps); - stdx::unordered_set<std::string> projectedFields; - for (auto&& [fieldName, _] : fieldIndexProps) { - if (projection_executor_utils::applyProjectionToOneField( - wildcardProjection->exec(), fieldName)) { - projectedFields.insert(fieldName); - } - } + stdx::unordered_set<std::string> fields; + QueryPlannerIXSelect::getFields(canonicalQuery->root(), &fields); + const auto projectedFields = projection_executor_utils::applyProjectionToFields( + wildcardProjection->exec(), fields); multikeyPathSet = getWildcardMultikeyPathSet(wam, opCtx, projectedFields, &mkAccessStats); @@ -293,8 +284,7 @@ void fillOutIndexEntries(OperationContext* opCtx, const CanonicalQuery* canonicalQuery, const CollectionPtr& collection, std::vector<IndexEntry>& entries) { - auto ii = collection->getIndexCatalog()->getIndexIterator( - opCtx, IndexCatalog::InclusionPolicy::kReady); + auto ii = collection->getIndexCatalog()->getIndexIterator(opCtx, false); while (ii->more()) { const IndexCatalogEntry* ice = ii->next(); @@ -607,8 +597,6 @@ public: StatusWith<std::unique_ptr<ResultType>> prepare() { const auto& mainColl = getMainCollection(); - - ON_BLOCK_EXIT([&] { CurOp::get(_opCtx)->stopQueryPlanningTimer(); }); if (!mainColl) { LOGV2_DEBUG(20921, 2, @@ -708,8 +696,10 @@ public: "Only one plan is available", "query"_attr = redact(_cq->toStringShort()), "planSummary"_attr = result->getPlanSummary()); + return std::move(result); } + return buildMultiPlan(std::move(solutions)); } @@ -1278,12 +1268,12 @@ std::unique_ptr<sbe::RuntimePlanner> makeRuntimePlannerIfNeeded( return nullptr; } -std::unique_ptr<PlanYieldPolicySBE> makeSbeYieldPolicy(OperationContext* opCtx, - PlanYieldPolicy::YieldPolicy policy, - const Yieldable* yieldable, - NamespaceString nss) { - return std::make_unique<PlanYieldPolicySBE>(opCtx, - policy, +std::unique_ptr<PlanYieldPolicySBE> makeSbeYieldPolicy( + OperationContext* opCtx, + PlanYieldPolicy::YieldPolicy requestedYieldPolicy, + const Yieldable* yieldable, + NamespaceString nss) { + return std::make_unique<PlanYieldPolicySBE>(requestedYieldPolicy, opCtx->getServiceContext()->getFastClockSource(), internalQueryExecYieldIterations.load(), Milliseconds{internalQueryExecYieldPeriodMS.load()}, @@ -1321,16 +1311,16 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getSlotBasedExe auto&& [roots, solutions] = planningResult->extractResultData(); // In some circumstances (e.g. when have multiple candidate plans or using a cached one), we // might need to execute the plan(s) to pick the best one or to confirm the choice. - if (auto runTimePlanner = makeRuntimePlannerIfNeeded(opCtx, - collections, - cq.get(), - solutions.size(), - planningResult->decisionWorks(), - planningResult->needsSubplanning(), - yieldPolicy.get(), - plannerParams.options)) { + if (auto planner = makeRuntimePlannerIfNeeded(opCtx, + collections, + cq.get(), + solutions.size(), + planningResult->decisionWorks(), + planningResult->needsSubplanning(), + yieldPolicy.get(), + plannerParams.options)) { // Do the runtime planning and pick the best candidate plan. - auto candidates = runTimePlanner->plan(std::move(solutions), std::move(roots)); + auto candidates = planner->plan(std::move(solutions), std::move(roots)); return plan_executor_factory::make(opCtx, std::move(cq), @@ -1401,11 +1391,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor( } } - // There's a special case of the projection optimization being skipped when a query has any - // user-defined "let" variable and the query may be run with SBE. Here we make sure the - // projection is optimized for the classic engine. - canonicalQuery->optimizeProjection(); - return getClassicExecutor( opCtx, mainColl, std::move(canonicalQuery), yieldPolicy, plannerParams); } @@ -1418,7 +1403,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor( PlanYieldPolicy::YieldPolicy yieldPolicy, size_t plannerOptions) { MultipleCollectionAccessor multi{collection}; - return getExecutor(opCtx, multi, std::move(canonicalQuery), @@ -1438,8 +1422,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorFind std::function<void(CanonicalQuery*)> extractAndAttachPipelineStages, bool permitYield, QueryPlannerParams plannerParams) { - auto yieldPolicy = permitYield ? PlanYieldPolicy::YieldPolicy::YIELD_AUTO - : PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY; + auto yieldPolicy = (permitYield && !opCtx->inMultiDocumentTransaction()) + ? PlanYieldPolicy::YieldPolicy::YIELD_AUTO + : PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY; if (OperationShardingState::isComingFromRouter(opCtx)) { plannerParams.options |= QueryPlannerParams::INCLUDE_SHARD_FILTER; @@ -1460,7 +1445,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorFind std::function<void(CanonicalQuery*)> extractAndAttachPipelineStages, bool permitYield, size_t plannerOptions) { - MultipleCollectionAccessor multi{*coll}; return getExecutorFind(opCtx, multi, @@ -1542,13 +1526,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele expCtx->setIsCappedDelete(); } - // If the parsed delete does not have a user-specified collation, set it from the collection - // default. - if (collection && parsedDelete->getRequest()->getCollation().isEmpty() && - collection->getDefaultCollator()) { - parsedDelete->setCollator(collection->getDefaultCollator()->clone()); - } - if (collection && collection->isCapped() && opCtx->inMultiDocumentTransaction()) { // This check is duplicated from CollectionImpl::deleteDocument() for two reasons: // - Performing a remove on an empty capped collection would not call @@ -1676,7 +1653,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele ClassicPrepareExecutionHelper helper{ opCtx, collection, ws.get(), cq.get(), nullptr, defaultPlannerOptions}; auto executionResult = helper.prepare(); - if (!executionResult.isOK()) { return executionResult.getStatus(); } @@ -1686,9 +1662,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele deleteStageParams->canonicalQuery = cq.get(); const bool batchDelete = - (deleteStageParams->isMulti && !opCtx->inMultiDocumentTransaction() && - !deleteStageParams->fromMigrate && !deleteStageParams->returnDeleted && - deleteStageParams->sort.isEmpty() && !deleteStageParams->numStatsForDoc) && + (deleteStageParams->isMulti && !deleteStageParams->fromMigrate && + !deleteStageParams->returnDeleted && deleteStageParams->sort.isEmpty() && + !deleteStageParams->numStatsForDoc) && ((gInternalBatchUserMultiDeletesForTest.load() && nss.ns() == "__internalBatchedDeletesTesting.Collection0") || (batchDeletesByDefault.shouldFail())); @@ -1864,7 +1840,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorUpda ClassicPrepareExecutionHelper helper{ opCtx, collection, ws.get(), cq.get(), nullptr, defaultPlannerOptions}; auto executionResult = helper.prepare(); - if (!executionResult.isOK()) { return executionResult.getStatus(); } @@ -2138,8 +2113,8 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun OperationContext* opCtx = expCtx->opCtx; std::unique_ptr<WorkingSet> ws = std::make_unique<WorkingSet>(); - auto findCommand = std::make_unique<FindCommandRequest>(nss); + auto findCommand = std::make_unique<FindCommandRequest>(nss); findCommand->setFilter(request.getQuery()); auto collation = request.getCollation().value_or(BSONObj()); findCommand->setCollation(collation); @@ -2160,7 +2135,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun } std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); - const auto yieldPolicy = PlanYieldPolicy::YieldPolicy::YIELD_AUTO; + const auto yieldPolicy = opCtx->inMultiDocumentTransaction() + ? PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY + : PlanYieldPolicy::YieldPolicy::YIELD_AUTO; const auto skip = request.getSkip().value_or(0); const auto limit = request.getLimit().value_or(0); @@ -2213,7 +2190,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun if (!executionResult.isOK()) { return executionResult.getStatus(); } - auto [root, querySolution] = executionResult.getValue()->extractResultData(); invariant(root); @@ -2222,7 +2198,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun expCtx.get(), collection, limit, skip, ws.get(), root.release()); // We must have a tree of stages in order to have a valid plan executor, but the query // solution may be NULL. Takes ownership of all args other than 'collection' and 'opCtx' - return plan_executor_factory::make(std::move(cq), std::move(ws), std::move(root), @@ -2418,8 +2393,8 @@ QueryPlannerParams fillOutPlannerParamsForDistinct(OperationContext* opCtx, // If the caller did not request a "strict" distinct scan then we may choose a plan which // unwinds arrays and treats each element in an array as its own key. const bool mayUnwindArrays = !(plannerOptions & QueryPlannerParams::STRICT_DISTINCT_ONLY); - auto ii = collection->getIndexCatalog()->getIndexIterator( - opCtx, IndexCatalog::InclusionPolicy::kReady); + std::unique_ptr<IndexCatalog::IndexIterator> ii = + collection->getIndexCatalog()->getIndexIterator(opCtx, false); auto query = parsedDistinct.getQuery()->getFindCommandRequest().getFilter(); while (ii->more()) { const IndexCatalogEntry* ice = ii->next(); @@ -2657,7 +2632,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDist auto expCtx = parsedDistinct->getQuery()->getExpCtx(); OperationContext* opCtx = expCtx->opCtx; - const auto yieldPolicy = PlanYieldPolicy::YieldPolicy::YIELD_AUTO; + const auto yieldPolicy = opCtx->inMultiDocumentTransaction() + ? PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY + : PlanYieldPolicy::YieldPolicy::YIELD_AUTO; if (!collection) { // Treat collections that do not exist as empty collections. |
