summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/optimizer/cascades
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/optimizer/cascades')
-rw-r--r--src/mongo/db/query/optimizer/cascades/cost_derivation.cpp2
-rw-r--r--src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp10
-rw-r--r--src/mongo/db/query/optimizer/cascades/memo.cpp24
-rw-r--r--src/mongo/db/query/optimizer/cascades/physical_rewriter.cpp16
-rw-r--r--src/mongo/db/query/optimizer/cascades/physical_rewriter.h2
-rw-r--r--src/mongo/db/query/optimizer/cascades/rewrite_queues.cpp28
-rw-r--r--src/mongo/db/query/optimizer/cascades/rewrite_queues.h29
7 files changed, 70 insertions, 41 deletions
diff --git a/src/mongo/db/query/optimizer/cascades/cost_derivation.cpp b/src/mongo/db/query/optimizer/cascades/cost_derivation.cpp
index d212c32c5a7..35be4caa4a3 100644
--- a/src/mongo/db/query/optimizer/cascades/cost_derivation.cpp
+++ b/src/mongo/db/query/optimizer/cascades/cost_derivation.cpp
@@ -124,7 +124,7 @@ public:
const LogicalProps& childLogicalProps =
_memo.getGroup(node.getGroupId())._logicalProperties;
// Notice that unlike all physical nodes, this logical node takes it cardinality directly
- // from the memo group logical property, igrnoring _cardinalityEstimate.
+ // from the memo group logical property, ignoring _cardinalityEstimate.
CEType baseCE = getPropertyConst<CardinalityEstimate>(childLogicalProps).getEstimate();
if (hasProperty<IndexingRequirement>(_physProps)) {
diff --git a/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp b/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
index dcd744b14ef..afed7401960 100644
--- a/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
+++ b/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
@@ -690,11 +690,13 @@ static void convertFilterToSargableNode(ABT::reference_type node,
}
}
- // If the filter has no constraints after removing no-ops, then rewrite the filter with a
- // predicate using the constant True.
if (conversion->_reqMap.empty()) {
- ctx.addNode(make<FilterNode>(Constant::boolean(true), filterNode.getChild()),
- true /*subtitute*/);
+ // If the filter has no constraints after removing no-ops, then replace with its child. We
+ // need to copy the child since we hold it by reference from the memo, and during
+ // subtitution the current group will be erased.
+
+ ABT newNode = filterNode.getChild();
+ ctx.addNode(newNode, true /*substitute*/);
return;
}
diff --git a/src/mongo/db/query/optimizer/cascades/memo.cpp b/src/mongo/db/query/optimizer/cascades/memo.cpp
index c702175bd4e..ec31837a919 100644
--- a/src/mongo/db/query/optimizer/cascades/memo.cpp
+++ b/src/mongo/db/query/optimizer/cascades/memo.cpp
@@ -87,17 +87,6 @@ const ABTVector& OrderPreservingABTSet::getVector() const {
return _vector;
}
-PhysRewriteEntry::PhysRewriteEntry(const double priority,
- PhysicalRewriteType rule,
- ABT node,
- std::vector<std::pair<ABT*, properties::PhysProps>> childProps,
- NodeCEMap nodeCEMap)
- : _priority(priority),
- _rule(rule),
- _node(std::move(node)),
- _childProps(std::move(childProps)),
- _nodeCEMap(std::move(nodeCEMap)) {}
-
PhysOptimizationResult::PhysOptimizationResult()
: PhysOptimizationResult(0, {}, CostType::kInfinity) {}
@@ -237,10 +226,14 @@ public:
// noop
}
- GroupIdType transport(const ABT& /*n*/,
+ GroupIdType transport(const ABT& n,
const MemoLogicalDelegatorNode& node,
- const VariableEnvironment& /*env*/) {
- return node.getGroupId();
+ const VariableEnvironment& env) {
+ if (_targetGroupMap.count(n.ref()) == 0) {
+ return node.getGroupId();
+ }
+
+ return addNodes(n, node, n, env, {});
}
void prepare(const ABT& n, const FilterNode& node, const VariableEnvironment& /*env*/) {
@@ -628,9 +621,6 @@ std::pair<MemoLogicalNodeId, bool> Memo::addNode(GroupIdType groupId,
ABT n,
LogicalRewriteType rule) {
uassert(6624052, "Attempting to insert a physical node", !n.is<ExclusivelyPhysicalNode>());
- uassert(6624053,
- "Attempting to insert a logical delegator node",
- !n.is<MemoLogicalDelegatorNode>());
Group& group = *_groups.at(groupId);
OrderPreservingABTSet& nodes = group._logicalNodes;
diff --git a/src/mongo/db/query/optimizer/cascades/physical_rewriter.cpp b/src/mongo/db/query/optimizer/cascades/physical_rewriter.cpp
index 82eedbd4ec7..4388f015f1a 100644
--- a/src/mongo/db/query/optimizer/cascades/physical_rewriter.cpp
+++ b/src/mongo/db/query/optimizer/cascades/physical_rewriter.cpp
@@ -33,7 +33,6 @@
#include "mongo/db/query/optimizer/cascades/implementers.h"
#include "mongo/db/query/optimizer/cascades/rewriter_rules.h"
#include "mongo/db/query/optimizer/explain.h"
-#include "mongo/db/query/optimizer/utils/rewriter_utils.h"
namespace mongo::optimizer::cascades {
@@ -139,21 +138,21 @@ static void printCandidateInfo(const ABT& node,
}
}
-void PhysicalRewriter::costAndRetainBestNode(ABT node,
+void PhysicalRewriter::costAndRetainBestNode(std::unique_ptr<ABT> node,
ChildPropsType childProps,
NodeCEMap nodeCEMap,
const PhysicalRewriteType rule,
const GroupIdType groupId,
PrefixId& prefixId,
PhysOptimizationResult& bestResult) {
- const CostAndCE nodeCostAndCE =
- _costDerivation.deriveCost(_memo, bestResult._physProps, node.ref(), childProps, nodeCEMap);
+ const CostAndCE nodeCostAndCE = _costDerivation.deriveCost(
+ _memo, bestResult._physProps, node->ref(), childProps, nodeCEMap);
const CostType nodeCost = nodeCostAndCE._cost;
uassert(6624056, "Must get non-infinity cost for physical node.", !nodeCost.isInfinite());
if (_memo.getDebugInfo().hasDebugLevel(3)) {
std::cout << "Requesting optimization\n";
- printCandidateInfo(node, groupId, nodeCost, childProps, bestResult);
+ printCandidateInfo(*node, groupId, nodeCost, childProps, bestResult);
}
const CostType childCostLimit =
@@ -166,14 +165,13 @@ void PhysicalRewriter::costAndRetainBestNode(ABT node,
std::cout << (success ? (improvement ? "Improved" : "Did not improve")
: "Failed optimizing")
<< "\n";
- printCandidateInfo(node, groupId, nodeCost, childProps, bestResult);
+ printCandidateInfo(*node, groupId, nodeCost, childProps, bestResult);
}
tassert(6678300,
"Retaining node with uninitialized rewrite rule",
rule != cascades::PhysicalRewriteType::Uninitialized);
- PhysNodeInfo candidateNodeInfo{
- unwrapConstFilter(std::move(node)), cost, nodeCost, nodeCostAndCE._ce, rule};
+ PhysNodeInfo candidateNodeInfo{std::move(*node), cost, nodeCost, nodeCostAndCE._ce, rule};
const bool keepRejectedPlans = _hints._keepRejectedPlans;
if (improvement) {
if (keepRejectedPlans && bestResult._nodeInfo) {
@@ -379,7 +377,7 @@ PhysicalRewriter::OptimizeGroupResult PhysicalRewriter::optimizeGroup(const Grou
NodeCEMap nodeCEMap = std::move(rewrite._nodeCEMap);
if (nodeCEMap.empty()) {
nodeCEMap.emplace(
- rewrite._node.cast<Node>(),
+ rewrite._node->cast<Node>(),
getPropertyConst<CardinalityEstimate>(logicalProps).getEstimate());
}
diff --git a/src/mongo/db/query/optimizer/cascades/physical_rewriter.h b/src/mongo/db/query/optimizer/cascades/physical_rewriter.h
index 205ecc62c3a..cb1b1b395af 100644
--- a/src/mongo/db/query/optimizer/cascades/physical_rewriter.h
+++ b/src/mongo/db/query/optimizer/cascades/physical_rewriter.h
@@ -71,7 +71,7 @@ public:
CostType costLimit);
private:
- void costAndRetainBestNode(ABT node,
+ void costAndRetainBestNode(std::unique_ptr<ABT> node,
ChildPropsType childProps,
NodeCEMap nodeCEMap,
PhysicalRewriteType rule,
diff --git a/src/mongo/db/query/optimizer/cascades/rewrite_queues.cpp b/src/mongo/db/query/optimizer/cascades/rewrite_queues.cpp
index c27ed44dd84..6475b704d0f 100644
--- a/src/mongo/db/query/optimizer/cascades/rewrite_queues.cpp
+++ b/src/mongo/db/query/optimizer/cascades/rewrite_queues.cpp
@@ -29,7 +29,6 @@
#include "mongo/db/query/optimizer/cascades/rewrite_queues.h"
#include "mongo/db/query/optimizer/cascades/rewriter_rules.h"
-#include "mongo/db/query/optimizer/utils/memo_utils.h"
#include <mongo/db/query/optimizer/defs.h>
namespace mongo::optimizer::cascades {
@@ -58,14 +57,39 @@ bool LogicalRewriteEntryComparator::operator()(
return x->_nodeId._index < y->_nodeId._index;
}
+PhysRewriteEntry::PhysRewriteEntry(const double priority,
+ PhysicalRewriteType rule,
+ std::unique_ptr<ABT> node,
+ std::vector<std::pair<ABT*, properties::PhysProps>> childProps,
+ NodeCEMap nodeCEMap)
+ : _priority(priority),
+ _rule(rule),
+ _node(std::move(node)),
+ _childProps(std::move(childProps)),
+ _nodeCEMap(std::move(nodeCEMap)) {}
+
void optimizeChildrenNoAssert(PhysRewriteQueue& queue,
const double priority,
const PhysicalRewriteType rule,
- ABT node,
+ std::unique_ptr<ABT> node,
ChildPropsType childProps,
NodeCEMap nodeCEMap) {
queue.emplace(std::make_unique<PhysRewriteEntry>(
priority, rule, std::move(node), std::move(childProps), std::move(nodeCEMap)));
}
+void optimizeChildrenNoAssert(PhysRewriteQueue& queue,
+ double priority,
+ PhysicalRewriteType rule,
+ ABT node,
+ ChildPropsType childProps,
+ NodeCEMap nodeCEMap) {
+ optimizeChildrenNoAssert(queue,
+ priority,
+ rule,
+ std::make_unique<ABT>(std::move(node)),
+ std::move(childProps),
+ std::move(nodeCEMap));
+}
+
} // namespace mongo::optimizer::cascades
diff --git a/src/mongo/db/query/optimizer/cascades/rewrite_queues.h b/src/mongo/db/query/optimizer/cascades/rewrite_queues.h
index b8e6ec66530..732d338a153 100644
--- a/src/mongo/db/query/optimizer/cascades/rewrite_queues.h
+++ b/src/mongo/db/query/optimizer/cascades/rewrite_queues.h
@@ -33,7 +33,6 @@
#include "mongo/db/query/optimizer/cascades/rewriter_rules.h"
#include "mongo/db/query/optimizer/node_defs.h"
-#include "mongo/db/query/optimizer/utils/rewriter_utils.h"
namespace mongo::optimizer::cascades {
@@ -75,7 +74,7 @@ static constexpr double kDefaultPriority = 10.0;
struct PhysRewriteEntry {
PhysRewriteEntry(double priority,
PhysicalRewriteType rule,
- ABT node,
+ std::unique_ptr<ABT> node,
ChildPropsType childProps,
NodeCEMap nodeCEMap);
@@ -88,9 +87,15 @@ struct PhysRewriteEntry {
// Rewrite rule that triggered this entry.
PhysicalRewriteType _rule;
- ABT _node;
+ // Node we are optimizing. This is typically a single node such as Filter with a
+ // MemoLogicalDelegator child, but could be a more complex tree.
+ std::unique_ptr<ABT> _node;
+ // For each child to optimize, we have associated physical properties. If we are optimizing the
+ // node under new properties (e.g. via enforcement) the map will contain a single entry using
+ // the address of the node itself (as opposed to the children to optimize).
ChildPropsType _childProps;
+ // Optional per-node CE. Used if the node is complex tree.
NodeCEMap _nodeCEMap;
};
@@ -106,6 +111,13 @@ using PhysRewriteQueue = std::priority_queue<std::unique_ptr<PhysRewriteEntry>,
void optimizeChildrenNoAssert(PhysRewriteQueue& queue,
double priority,
PhysicalRewriteType rule,
+ std::unique_ptr<ABT> node,
+ ChildPropsType childProps,
+ NodeCEMap nodeCEMap);
+
+void optimizeChildrenNoAssert(PhysRewriteQueue& queue,
+ double priority,
+ PhysicalRewriteType rule,
ABT node,
ChildPropsType childProps,
NodeCEMap nodeCEMap);
@@ -116,7 +128,8 @@ static void optimizeChildren(PhysRewriteQueue& queue,
ABT node,
ChildPropsType childProps) {
static_assert(canBePhysicalNode<T>(), "Can only optimize a physical node.");
- optimizeChildrenNoAssert(queue, priority, rule, std::move(node), std::move(childProps), {});
+ optimizeChildrenNoAssert(
+ queue, priority, rule, std::move(node), std::move(childProps), {} /*nodeCEMap*/);
}
template <class T, PhysicalRewriteType rule>
@@ -131,7 +144,7 @@ static void optimizeChild(PhysRewriteQueue& queue,
template <class T, PhysicalRewriteType rule>
static void optimizeChild(PhysRewriteQueue& queue, const double priority, ABT node) {
- optimizeChildren<T, rule>(queue, priority, std::move(node), {});
+ optimizeChildren<T, rule>(queue, priority, std::move(node), {} /*nodeCEMap*/);
}
@@ -140,8 +153,10 @@ void optimizeUnderNewProperties(cascades::PhysRewriteQueue& queue,
const double priority,
ABT child,
properties::PhysProps props) {
- optimizeChild<FilterNode, rule>(
- queue, priority, wrapConstFilter(std::move(child)), std::move(props));
+ auto nodePtr = std::make_unique<ABT>(std::move(child));
+ ChildPropsType childProps{{nodePtr.get(), std::move(props)}};
+ optimizeChildrenNoAssert(
+ queue, priority, rule, std::move(nodePtr), std::move(childProps), {} /*nodeCEMap*/);
}
template <class T, PhysicalRewriteType rule>