diff options
Diffstat (limited to 'src/mongo/db/exec/sbe')
-rw-r--r-- | src/mongo/db/exec/sbe/abt/abt_lower.cpp | 47 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/ix_scan.cpp | 111 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/ix_scan.h | 38 |
3 files changed, 54 insertions, 142 deletions
diff --git a/src/mongo/db/exec/sbe/abt/abt_lower.cpp b/src/mongo/db/exec/sbe/abt/abt_lower.cpp index f32fe8da661..a706d150d61 100644 --- a/src/mongo/db/exec/sbe/abt/abt_lower.cpp +++ b/src/mongo/db/exec/sbe/abt/abt_lower.cpp @@ -1008,45 +1008,22 @@ std::unique_ptr<sbe::PlanStage> SBENodeLowering::walk(const IndexScanNode& n, co const PlanNodeId planNodeId = _nodeToGroupPropsMap.at(&n)._planNodeId; auto projectForKeyStringBounds = sbe::makeS<sbe::LimitSkipStage>( sbe::makeS<sbe::CoScanStage>(planNodeId), 1, boost::none, planNodeId); - if (hasLowerBound) { - seekKeySlotLower = _slotIdGenerator.generate(); - correlatedSlotsForJoin.push_back(seekKeySlotLower.value()); - projectForKeyStringBounds = sbe::makeProjectStage(std::move(projectForKeyStringBounds), - planNodeId, - seekKeySlotLower.value(), - std::move(lowerBoundExpr)); - } - if (hasUpperBound) { - seekKeySlotUpper = _slotIdGenerator.generate(); - correlatedSlotsForJoin.push_back(seekKeySlotUpper.value()); - projectForKeyStringBounds = sbe::makeProjectStage(std::move(projectForKeyStringBounds), - planNodeId, - seekKeySlotUpper.value(), - std::move(upperBoundExpr)); - } // Unused. boost::optional<sbe::value::SlotId> resultSlot; - auto result = sbe::makeS<sbe::IndexScanStage>(nss.uuid().get(), - indexDefName, - !indexSpec.isReverseOrder(), - resultSlot, - ridSlot, - boost::none, - indexKeysToInclude, - vars, - seekKeySlotLower, - seekKeySlotUpper, - nullptr /*yieldPolicy*/, - planNodeId); - - return sbe::makeS<sbe::LoopJoinStage>(std::move(projectForKeyStringBounds), - std::move(result), - sbe::makeSV(), - std::move(correlatedSlotsForJoin), - nullptr, - planNodeId); + return sbe::makeS<sbe::IndexScanStage>(nss.uuid().get(), + indexDefName, + !indexSpec.isReverseOrder(), + resultSlot, + ridSlot, + boost::none, + indexKeysToInclude, + vars, + std::move(lowerBoundExpr), + std::move(upperBoundExpr), + nullptr /*yieldPolicy*/, + planNodeId); } std::unique_ptr<sbe::PlanStage> SBENodeLowering::walk(const SeekNode& n, diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp index ba8cd9704e4..520e68fe074 100644 --- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp +++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp @@ -47,11 +47,11 @@ IndexScanStage::IndexScanStage(UUID collUuid, boost::optional<value::SlotId> snapshotIdSlot, IndexKeysInclusionSet indexKeysToInclude, value::SlotVector vars, - boost::optional<value::SlotId> seekKeySlotLow, - boost::optional<value::SlotId> seekKeySlotHigh, + std::unique_ptr<EExpression> seekKeyLow, + std::unique_ptr<EExpression> seekKeyHigh, PlanYieldPolicy* yieldPolicy, PlanNodeId nodeId) - : PlanStage(seekKeySlotLow ? "ixseek"_sd : "ixscan"_sd, yieldPolicy, nodeId), + : PlanStage(seekKeyLow ? "ixseek"_sd : "ixscan"_sd, yieldPolicy, nodeId), _collUuid(collUuid), _indexName(indexName), _forward(forward), @@ -60,40 +60,11 @@ IndexScanStage::IndexScanStage(UUID collUuid, _snapshotIdSlot(snapshotIdSlot), _indexKeysToInclude(indexKeysToInclude), _vars(std::move(vars)), - _seekKeySlotLow(seekKeySlotLow), - _seekKeySlotHigh(seekKeySlotHigh) { + _seekKeyLow(std::move(seekKeyLow)), + _seekKeyHigh(std::move(seekKeyHigh)) { // The valid state is when both boundaries, or none is set, or only low key is set. - invariant((_seekKeySlotLow && _seekKeySlotHigh) || (!_seekKeySlotLow && !_seekKeySlotHigh) || - (_seekKeySlotLow && !_seekKeySlotHigh)); - - invariant(_indexKeysToInclude.count() == _vars.size()); -} -IndexScanStage::IndexScanStage(UUID collUuid, - StringData indexName, - bool forward, - boost::optional<value::SlotId> recordSlot, - boost::optional<value::SlotId> recordIdSlot, - boost::optional<value::SlotId> snapshotIdSlot, - IndexKeysInclusionSet indexKeysToInclude, - value::SlotVector vars, - std::unique_ptr<EExpression> seekKeyLowVar, - std::unique_ptr<EExpression> seekKeyHighVar, - PlanYieldPolicy* yieldPolicy, - PlanNodeId nodeId) - : PlanStage(seekKeyLowVar ? "ixseek"_sd : "ixscan"_sd, yieldPolicy, nodeId), - _collUuid(collUuid), - _indexName(indexName), - _forward(forward), - _recordSlot(recordSlot), - _recordIdSlot(recordIdSlot), - _snapshotIdSlot(snapshotIdSlot), - _indexKeysToInclude(indexKeysToInclude), - _vars(std::move(vars)), - _seekKeyLowVar(std::move(seekKeyLowVar)), - _seekKeyHighVar(std::move(seekKeyHighVar)) { - // The valid state is when both boundaries, or none is set, or only low key is set. - invariant((_seekKeyLowVar && _seekKeyHighVar) || (!_seekKeyLowVar && !_seekKeyHighVar) || - (_seekKeyLowVar && !_seekKeyHighVar)); + invariant((_seekKeyLow && _seekKeyHigh) || (!_seekKeyLow && !_seekKeyHigh) || + (_seekKeyLow && !_seekKeyHigh)); invariant(_indexKeysToInclude.count() == _vars.size()); } @@ -107,8 +78,8 @@ std::unique_ptr<PlanStage> IndexScanStage::clone() const { _snapshotIdSlot, _indexKeysToInclude, _vars, - _seekKeySlotLow, - _seekKeySlotHigh, + _seekKeyLow->clone(), + _seekKeyHigh->clone(), _yieldPolicy, _commonStats.nodeId); } @@ -132,11 +103,13 @@ void IndexScanStage::prepare(CompileCtx& ctx) { uassert(4822821, str::stream() << "duplicate slot: " << _vars[idx], inserted); } - if (_seekKeySlotLow) { - _seekKeyLowAccessor = ctx.getAccessor(*_seekKeySlotLow); + if (_seekKeyLow) { + ctx.root = this; + _seekKeyLowCodes = _seekKeyLow->compile(ctx); } - if (_seekKeySlotHigh) { - _seekKeyHiAccessor = ctx.getAccessor(*_seekKeySlotHigh); + if (_seekKeyHigh) { + ctx.root = this; + _seekKeyHighCodes = _seekKeyHigh->compile(ctx); _seekKeyHighHolder = std::make_unique<value::OwnedValueAccessor>(); } _seekKeyLowHolder = std::make_unique<value::OwnedValueAccessor>(); @@ -162,16 +135,6 @@ void IndexScanStage::prepare(CompileCtx& ctx) { value::TypeTags::NumberInt64, value::bitcastFrom<uint64_t>(_opCtx->recoveryUnit()->getSnapshotId().toNumber())); } - - if (_seekKeyLowVar) { - ctx.root = this; - _seekKeyLowCodes = _seekKeyLowVar->compile(ctx); - } - if (_seekKeyHighVar) { - ctx.root = this; - _seekKeyHighCodes = _seekKeyHighVar->compile(ctx); - _seekKeyHighHolder = std::make_unique<value::OwnedValueAccessor>(); - } } value::SlotAccessor* IndexScanStage::getAccessor(CompileCtx& ctx, value::SlotId slot) { @@ -317,34 +280,28 @@ void IndexScanStage::open(bool reOpen) { _cursor = entry->accessMethod()->asSortedData()->newCursor(_opCtx, _forward); } - if (_seekKeyLowAccessor && _seekKeyHiAccessor) { - auto [tagLow, valLow] = _seekKeyLowAccessor->getViewOfValue(); + if (_seekKeyLow && _seekKeyHigh) { + auto [ownedLow, tagLow, valLow] = _bytecode.run(_seekKeyLowCodes.get()); const auto msgTagLow = tagLow; uassert(4822851, str::stream() << "seek key is wrong type: " << msgTagLow, tagLow == value::TypeTags::ksValue); - _seekKeyLowHolder->reset(false, tagLow, valLow); + _seekKeyLowHolder->reset(ownedLow, tagLow, valLow); - auto [tagHi, valHi] = _seekKeyHiAccessor->getViewOfValue(); + auto [ownedHi, tagHi, valHi] = _bytecode.run(_seekKeyHighCodes.get()); const auto msgTagHi = tagHi; uassert(4822852, str::stream() << "seek key is wrong type: " << msgTagHi, tagHi == value::TypeTags::ksValue); - _seekKeyHighHolder->reset(false, tagHi, valHi); - } else if (_seekKeyLowAccessor) { - auto [tagLow, valLow] = _seekKeyLowAccessor->getViewOfValue(); + _seekKeyHighHolder->reset(ownedHi, tagHi, valHi); + } else if (_seekKeyLow) { + auto [ownedLow, tagLow, valLow] = _bytecode.run(_seekKeyLowCodes.get()); const auto msgTagLow = tagLow; uassert(4822853, str::stream() << "seek key is wrong type: " << msgTagLow, tagLow == value::TypeTags::ksValue); - _seekKeyLowHolder->reset(false, tagLow, valLow); - } else if (_seekKeyLowVar && _seekKeyHighVar) { - auto [ownedLow, tagLow, valLow] = _bytecode.run(_seekKeyLowCodes.get()); _seekKeyLowHolder->reset(ownedLow, tagLow, valLow); - - auto [ownedHigh, tagHigh, valHigh] = _bytecode.run(_seekKeyHighCodes.get()); - _seekKeyHighHolder->reset(ownedHigh, tagHigh, valHigh); } else { auto sdi = entry->accessMethod()->asSortedData()->getSortedDataInterface(); KeyString::Builder kb(sdi->getKeyStringVersion(), @@ -454,6 +411,7 @@ std::unique_ptr<PlanStageStats> IndexScanStage::getStats(bool includeDebugInfo) ret->specific = std::make_unique<IndexScanStats>(_specificStats); if (includeDebugInfo) { + DebugPrinter printer; BSONObjBuilder bob; bob.append("indexName", _indexName); bob.appendNumber("keysExamined", static_cast<long long>(_specificStats.keysExamined)); @@ -468,11 +426,11 @@ std::unique_ptr<PlanStageStats> IndexScanStage::getStats(bool includeDebugInfo) if (_snapshotIdSlot) { bob.appendNumber("snapshotIdSlot", static_cast<long long>(*_snapshotIdSlot)); } - if (_seekKeySlotLow) { - bob.appendNumber("seekKeySlotLow", static_cast<long long>(*_seekKeySlotLow)); + if (_seekKeyLow) { + bob.append("seekKeyLow", printer.print(_seekKeyLow->debugPrint())); } - if (_seekKeySlotHigh) { - bob.appendNumber("seekKeySlotHigh", static_cast<long long>(*_seekKeySlotHigh)); + if (_seekKeyHigh) { + bob.append("seekKeyHigh", printer.print(_seekKeyHigh->debugPrint())); } bob.append("outputSlots", _vars.begin(), _vars.end()); bob.append("indexKeysToInclude", _indexKeysToInclude.to_string()); @@ -489,17 +447,10 @@ const SpecificStats* IndexScanStage::getSpecificStats() const { std::vector<DebugPrinter::Block> IndexScanStage::debugPrint() const { auto ret = PlanStage::debugPrint(); - if (_seekKeySlotLow) { - DebugPrinter::addIdentifier(ret, _seekKeySlotLow.get()); - if (_seekKeySlotHigh) { - DebugPrinter::addIdentifier(ret, _seekKeySlotHigh.get()); - } else { - DebugPrinter::addIdentifier(ret, DebugPrinter::kNoneKeyword); - } - } else if (_seekKeyLowVar) { - DebugPrinter::addBlocks(ret, _seekKeyLowVar->debugPrint()); - if (_seekKeyHighVar) { - DebugPrinter::addBlocks(ret, _seekKeyHighVar->debugPrint()); + if (_seekKeyLow) { + DebugPrinter::addBlocks(ret, _seekKeyLow->debugPrint()); + if (_seekKeyHigh) { + DebugPrinter::addBlocks(ret, _seekKeyHigh->debugPrint()); } else { DebugPrinter::addIdentifier(ret, DebugPrinter::kNoneKeyword); } diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.h b/src/mongo/db/exec/sbe/stages/ix_scan.h index 3e61a086670..c57389b3434 100644 --- a/src/mongo/db/exec/sbe/stages/ix_scan.h +++ b/src/mongo/db/exec/sbe/stages/ix_scan.h @@ -41,14 +41,14 @@ namespace mongo::sbe { /** * A stage that iterates the entries of a collection index, starting from a bound specified by the - * value in 'seekKeySlotLow' and ending (via IS_EOF) with the 'seekKeySlotHigh' bound. (An - * unspecified 'seekKeySlotHigh' scans to the end of the index. Leaving both bounds unspecified + * value in 'seekKeyLow' and ending (via IS_EOF) with the 'seekKeyHigh' bound. (An + * unspecified 'seekKeyHigh' scans to the end of the index. Leaving both bounds unspecified * scans the index from beginning to end.) * - * The input 'seekKeySlotLow' and 'seekKeySlotHigh' slots get read as part of the open (or re-open) - * call. A common use case for an IndexScanStage is to place it as the inner child of LoopJoinStage. - * The outer side of the LoopJoinStage determines the bounds, and the inner IndexScanStage iterates - * through all the entries within those bounds. + * The input 'seekKeyLow' and 'seekKeyHigh' EExpressions get evaluated as part of the open + * (or re-open) call. A common use case for an IndexScanStage is to place it as the inner child of + * LoopJoinStage. The outer side of the LoopJoinStage determines the bounds, and the inner + * IndexScanStage iterates through all the entries within those bounds. * * The "output" slots are * - 'recordSlot': the "KeyString" representing the index entry, @@ -82,21 +82,8 @@ public: boost::optional<value::SlotId> snapshotIdSlot, IndexKeysInclusionSet indexKeysToInclude, value::SlotVector vars, - boost::optional<value::SlotId> seekKeySlotLow, - boost::optional<value::SlotId> seekKeySlotHigh, - PlanYieldPolicy* yieldPolicy, - PlanNodeId nodeId); - - IndexScanStage(UUID collUuid, - StringData indexName, - bool forward, - boost::optional<value::SlotId> recordSlot, - boost::optional<value::SlotId> recordIdSlot, - boost::optional<value::SlotId> snapshotIdSlot, - IndexKeysInclusionSet indexKeysToInclude, - value::SlotVector vars, - std::unique_ptr<EExpression> seekKeyLowVar, - std::unique_ptr<EExpression> seekKeyHighVar, + std::unique_ptr<EExpression> seekKeyLow, + std::unique_ptr<EExpression> seekKeyHigh, PlanYieldPolicy* yieldPolicy, PlanNodeId nodeId); @@ -142,19 +129,16 @@ private: const boost::optional<value::SlotId> _snapshotIdSlot; const IndexKeysInclusionSet _indexKeysToInclude; const value::SlotVector _vars; - const boost::optional<value::SlotId> _seekKeySlotLow; - const boost::optional<value::SlotId> _seekKeySlotHigh; - std::unique_ptr<EExpression> _seekKeyLowVar; - std::unique_ptr<EExpression> _seekKeyHighVar; + std::unique_ptr<EExpression> _seekKeyLow; + std::unique_ptr<EExpression> _seekKeyHigh; - // For the EExpression overload for seek keys. + // Carries the compiled bytecode for the above '_seekKeyLow' and '_seekKeyHigh'. std::unique_ptr<vm::CodeFragment> _seekKeyLowCodes; std::unique_ptr<vm::CodeFragment> _seekKeyHighCodes; vm::ByteCode _bytecode; - // These members are default constructed to boost::none and are initialized when 'prepare()' // is called. Once they are set, they are never modified again. boost::optional<NamespaceString> _collName; |