This is an automated email from the ASF dual-hosted git repository.
jakevin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7d840cfa51e [enhancement](Nereids): add builder for hyper graph
(#30061)
7d840cfa51e is described below
commit 7d840cfa51ec3685ceef3985b8c0a329af8163a1
Author: 谢健 <[email protected]>
AuthorDate: Tue Jan 23 15:31:53 2024 +0800
[enhancement](Nereids): add builder for hyper graph (#30061)
---
.../doris/nereids/jobs/joinorder/JoinOrderJob.java | 7 +-
.../jobs/joinorder/hypergraph/HyperGraph.java | 715 ++++++++++-----------
.../joinorder/hypergraph/node/StructInfoNode.java | 16 -
.../nereids/rules/exploration/mv/StructInfo.java | 2 +-
.../joinorder/hypergraph/CompareOuterJoinTest.java | 24 +-
.../jobs/joinorder/hypergraph/InferJoinTest.java | 16 +-
.../joinorder/hypergraph/InferPredicateTest.java | 4 +-
.../joinorder/hypergraph/PullupExpressionTest.java | 16 +-
.../rules/exploration/mv/BuildStructInfoTest.java | 8 +-
.../rules/exploration/mv/HyperGraphAggTest.java | 6 +-
.../exploration/mv/HyperGraphComparatorTest.java | 16 +-
.../doris/nereids/util/HyperGraphBuilder.java | 4 +-
12 files changed, 398 insertions(+), 436 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/JoinOrderJob.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/JoinOrderJob.java
index b25793090bc..08e40f84a6c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/JoinOrderJob.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/JoinOrderJob.java
@@ -73,11 +73,12 @@ public class JoinOrderJob extends Job {
}
private Group optimizeJoin(Group group) {
- HyperGraph hyperGraph = HyperGraph.toDPhyperGraph(group);
- for (AbstractNode node : hyperGraph.getNodes()) {
+ HyperGraph.Builder builder = HyperGraph.builderForDPhyper(group);
+ for (AbstractNode node : builder.getNodes()) {
DPhyperNode dPhyperNode = (DPhyperNode) node;
- hyperGraph.updateNode(node.getIndex(),
optimizePlan(dPhyperNode.getGroup()));
+ builder.updateNode(node.getIndex(),
optimizePlan(dPhyperNode.getGroup()));
}
+ HyperGraph hyperGraph = builder.build();
// TODO: Right now, we just hardcode the limit with 10000, maybe we
need a better way to set it
int limit = 1000;
PlanReceiver planReceiver = new PlanReceiver(this.context, limit,
hyperGraph,
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
index 8a0bd8daaab..8472837d79e 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
@@ -42,6 +42,8 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalProject;
import org.apache.doris.nereids.util.PlanUtils;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
@@ -58,21 +60,25 @@ import java.util.stream.Collectors;
* It's used for join ordering
*/
public class HyperGraph {
- private final List<JoinEdge> joinEdges = new ArrayList<>();
- private final List<FilterEdge> filterEdges = new ArrayList<>();
- private final List<AbstractNode> nodes = new ArrayList<>();
- private final HashMap<Slot, Long> slotToNodeMap = new HashMap<>();
// record all edges that can be placed on the subgraph
private final Map<Long, BitSet> treeEdgesCache = new HashMap<>();
+ private final List<JoinEdge> joinEdges;
+ private final List<FilterEdge> filterEdges;
+ private final List<AbstractNode> nodes;
private final Set<Slot> finalOutputs;
// Record the complex project expression for some subgraph
// e.g. project (a + b)
// |-- join(t1.a = t2.b)
- private final HashMap<Long, List<NamedExpression>> complexProject = new
HashMap<>();
+ private final Map<Long, List<NamedExpression>> complexProject;
- HyperGraph(Set<Slot> finalOutputs) {
+ HyperGraph(Set<Slot> finalOutputs, List<JoinEdge> joinEdges,
List<AbstractNode> nodes, List<FilterEdge> filterEdges,
+ Map<Long, List<NamedExpression>> complexProject) {
this.finalOutputs = ImmutableSet.copyOf(finalOutputs);
+ this.joinEdges = ImmutableList.copyOf(joinEdges);
+ this.nodes = ImmutableList.copyOf(nodes);
+ this.complexProject = ImmutableMap.copyOf(complexProject);
+ this.filterEdges = ImmutableList.copyOf(filterEdges);
}
public List<JoinEdge> getJoinEdges() {
@@ -103,191 +109,10 @@ public class HyperGraph {
return nodes.get(index);
}
- /**
- * Store the relation between Alias Slot and Original Slot and its
expression
- * e.g.,
- * a = b
- * |--- project((c + d) as b)
- * <p>
- * a = b
- * |--- project((c + 1) as b)
- *
- * @param alias The alias Expression in project Operator
- */
- public boolean addAlias(Alias alias, long subTreeNodes) {
- Slot aliasSlot = alias.toSlot();
- if (slotToNodeMap.containsKey(aliasSlot)) {
- return true;
- }
- long bitmap = LongBitmap.newBitmap();
- for (Slot slot : alias.getInputSlots()) {
- bitmap = LongBitmap.or(bitmap, slotToNodeMap.get(slot));
- }
- // The case hit when there are some constant aliases such as:
- // select * from t1 join (
- // select *, 1 as b1 from t2)
- // on t1.b = b1
- // just reference them all for this slot
- if (bitmap == 0) {
- bitmap = subTreeNodes;
- }
- Preconditions.checkArgument(bitmap > 0, "slot must belong to some
table");
- slotToNodeMap.put(aliasSlot, bitmap);
- if (!complexProject.containsKey(bitmap)) {
- complexProject.put(bitmap, new ArrayList<>());
- }
- alias = (Alias) PlanUtils.mergeProjections(complexProject.get(bitmap),
Lists.newArrayList(alias)).get(0);
-
- complexProject.get(bitmap).add(alias);
- return true;
- }
-
- /**
- * add end node to HyperGraph
- *
- * @param group The group that is the end node in graph
- * @return return the node index
- */
- private int addDPHyperNode(Group group) {
- for (Slot slot : group.getLogicalExpression().getPlan().getOutput()) {
- Preconditions.checkArgument(!slotToNodeMap.containsKey(slot));
- slotToNodeMap.put(slot, LongBitmap.newBitmap(nodes.size()));
- }
- nodes.add(new DPhyperNode(nodes.size(), group));
- return nodes.size() - 1;
- }
-
- /**
- * add end node to HyperGraph
- *
- * @param plan The plan that is the end node in graph
- * @return return the node index
- */
- private int addStructInfoNode(Plan plan) {
- for (Slot slot : plan.getOutput()) {
- Preconditions.checkArgument(!slotToNodeMap.containsKey(slot));
- slotToNodeMap.put(slot, LongBitmap.newBitmap(nodes.size()));
- }
- nodes.add(new StructInfoNode(nodes.size(), plan));
- return nodes.size() - 1;
- }
-
- private int addStructInfoNode(List<HyperGraph> childGraphs) {
- for (Slot slot : childGraphs.get(0).finalOutputs) {
- Preconditions.checkArgument(!slotToNodeMap.containsKey(slot));
- slotToNodeMap.put(slot, LongBitmap.newBitmap(nodes.size()));
- }
- nodes.add(new StructInfoNode(nodes.size(), childGraphs));
- return nodes.size() - 1;
- }
-
- public void updateNode(int idx, Group group) {
- Preconditions.checkArgument(nodes.get(idx) instanceof DPhyperNode);
- nodes.set(idx, ((DPhyperNode) nodes.get(idx)).withGroup(group));
- }
-
- public HashMap<Long, List<NamedExpression>> getComplexProject() {
+ public Map<Long, List<NamedExpression>> getComplexProject() {
return complexProject;
}
- private void addEdgeOfInfo(JoinEdge edge) {
- long nodeMap = calNodeMap(edge.getInputSlots());
- Preconditions.checkArgument(LongBitmap.getCardinality(nodeMap) > 1,
- "edge must have more than one ends");
- long left = LongBitmap.newBitmap(LongBitmap.nextSetBit(nodeMap, 0));
- long right = LongBitmap.newBitmapDiff(nodeMap, left);
- this.joinEdges.add(new JoinEdge(edge.getJoin(), joinEdges.size(),
- null, null, 0, left, right));
- }
-
- /**
- * try to add edge for join group
- *
- * @param join The join plan
- */
- private BitSet addJoin(LogicalJoin<?, ?> join,
- Pair<BitSet, Long> leftEdgeNodes, Pair<BitSet, Long>
rightEdgeNodes) {
- HashMap<Pair<Long, Long>, Pair<List<Expression>, List<Expression>>>
conjuncts = new HashMap<>();
- for (Expression expression : join.getHashJoinConjuncts()) {
- // TODO: avoid calling calculateEnds if calNodeMap's results are
same
- Pair<Long, Long> ends =
calculateEnds(calNodeMap(expression.getInputSlots()), leftEdgeNodes,
- rightEdgeNodes);
- if (!conjuncts.containsKey(ends)) {
- conjuncts.put(ends, Pair.of(new ArrayList<>(), new
ArrayList<>()));
- }
- conjuncts.get(ends).first.add(expression);
- }
- for (Expression expression : join.getOtherJoinConjuncts()) {
- Pair<Long, Long> ends =
calculateEnds(calNodeMap(expression.getInputSlots()), leftEdgeNodes,
- rightEdgeNodes);
- if (!conjuncts.containsKey(ends)) {
- conjuncts.put(ends, Pair.of(new ArrayList<>(), new
ArrayList<>()));
- }
- conjuncts.get(ends).second.add(expression);
- }
-
- BitSet curJoinEdges = new BitSet();
- for (Map.Entry<Pair<Long, Long>, Pair<List<Expression>,
List<Expression>>> entry : conjuncts
- .entrySet()) {
- LogicalJoin<?, ?> singleJoin = new
LogicalJoin<>(join.getJoinType(), entry.getValue().first,
- entry.getValue().second,
- new DistributeHint(DistributeType.NONE),
join.getMarkJoinSlotReference(),
- Lists.newArrayList(join.left(), join.right()));
- Pair<Long, Long> ends = entry.getKey();
- JoinEdge edge = new JoinEdge(singleJoin, joinEdges.size(),
leftEdgeNodes.first, rightEdgeNodes.first,
- LongBitmap.newBitmapUnion(leftEdgeNodes.second,
rightEdgeNodes.second), ends.first, ends.second);
- for (int nodeIndex :
LongBitmap.getIterator(edge.getReferenceNodes())) {
- nodes.get(nodeIndex).attachEdge(edge);
- }
- curJoinEdges.set(edge.getIndex());
- joinEdges.add(edge);
- }
- curJoinEdges.stream().forEach(i ->
joinEdges.get(i).addCurJoinEdges(curJoinEdges));
- curJoinEdges.stream().forEach(i ->
ConflictRulesMaker.makeJoinConflictRules(joinEdges.get(i), joinEdges));
- curJoinEdges.stream().forEach(i ->
- ConflictRulesMaker.makeFilterConflictRules(joinEdges.get(i),
joinEdges, filterEdges));
- return curJoinEdges;
- // In MySQL, each edge is reversed and store in edges again for
reducing the branch miss
- // We don't implement this trick now.
- }
-
- private BitSet addFilter(LogicalFilter<?> filter, Pair<BitSet, Long>
childEdgeNodes) {
- FilterEdge edge = new FilterEdge(filter, filterEdges.size(),
childEdgeNodes.first, childEdgeNodes.second,
- childEdgeNodes.second);
- filterEdges.add(edge);
- BitSet bitSet = new BitSet();
- bitSet.set(edge.getIndex());
- return bitSet;
- }
-
- // Try to calculate the ends of an expression.
- // left = ref_nodes \cap left_tree , right = ref_nodes \cap right_tree
- // if left = 0, recursively calculate it in left tree
- private Pair<Long, Long> calculateEnds(long allNodes, Pair<BitSet, Long>
leftEdgeNodes,
- Pair<BitSet, Long> rightEdgeNodes) {
- long left = LongBitmap.newBitmapIntersect(allNodes,
leftEdgeNodes.second);
- long right = LongBitmap.newBitmapIntersect(allNodes,
rightEdgeNodes.second);
- if (left == 0) {
- Preconditions.checkArgument(leftEdgeNodes.first.cardinality() > 0,
- "the number of the table which expression reference is
less 2");
- Pair<BitSet, Long> llEdgesNodes =
joinEdges.get(leftEdgeNodes.first.nextSetBit(0)).getLeftEdgeNodes(
- joinEdges);
- Pair<BitSet, Long> lrEdgesNodes =
joinEdges.get(leftEdgeNodes.first.nextSetBit(0)).getRightEdgeNodes(
- joinEdges);
- return calculateEnds(allNodes, llEdgesNodes, lrEdgesNodes);
- }
- if (right == 0) {
- Preconditions.checkArgument(rightEdgeNodes.first.cardinality() > 0,
- "the number of the table which expression reference is
less 2");
- Pair<BitSet, Long> rlEdgesNodes =
joinEdges.get(rightEdgeNodes.first.nextSetBit(0)).getLeftEdgeNodes(
- joinEdges);
- Pair<BitSet, Long> rrEdgesNodes =
joinEdges.get(rightEdgeNodes.first.nextSetBit(0)).getRightEdgeNodes(
- joinEdges);
- return calculateEnds(allNodes, rlEdgesNodes, rrEdgesNodes);
- }
- return Pair.of(left, right);
- }
-
public BitSet getEdgesInOperator(long left, long right) {
BitSet operatorEdgesMap = new BitSet();
operatorEdgesMap.or(getEdgesInTree(LongBitmap.or(left, right)));
@@ -312,152 +137,36 @@ public class HyperGraph {
return treeEdgesCache.get(treeNodesMap);
}
- private long calNodeMap(Set<Slot> slots) {
- Preconditions.checkArgument(slots.size() != 0);
- long bitmap = LongBitmap.newBitmap();
- for (Slot slot : slots) {
- Preconditions.checkArgument(slotToNodeMap.containsKey(slot));
- bitmap = LongBitmap.or(bitmap, slotToNodeMap.get(slot));
- }
- return bitmap;
- }
-
- public static List<HyperGraph> toStructInfo(Plan plan) {
- HyperGraph hyperGraph = new HyperGraph(plan.getOutputSet());
- hyperGraph.buildStructInfo(plan);
- return hyperGraph.flatChildren();
- }
-
- private List<HyperGraph> flatChildren() {
- if (nodes.stream().noneMatch(n -> ((StructInfoNode) n).needToFlat())) {
- return Lists.newArrayList(this);
- }
- List<HyperGraph> res = new ArrayList<>();
- res.add(new HyperGraph(finalOutputs));
- for (AbstractNode node : nodes) {
- res = flatChild((StructInfoNode) node, res);
- }
- for (JoinEdge edge : joinEdges) {
- res.forEach(g -> g.addEdgeOfInfo(edge));
- }
- return res;
- }
-
- private List<HyperGraph> flatChild(StructInfoNode infoNode,
List<HyperGraph> hyperGraphs) {
- if (!infoNode.needToFlat()) {
- hyperGraphs.forEach(g -> g.addStructInfoNode(infoNode.getPlan()));
- return hyperGraphs;
- }
- return hyperGraphs.stream().flatMap(g ->
- infoNode.getGraphs().stream().map(subGraph -> {
- HyperGraph hyperGraph = new HyperGraph(g.finalOutputs);
- hyperGraph.addStructInfo(g);
- hyperGraph.addStructInfo(subGraph);
- return hyperGraph;
- })
- ).collect(Collectors.toList());
- }
-
- public static HyperGraph toDPhyperGraph(Group group) {
- HyperGraph hyperGraph = new
HyperGraph(group.getLogicalProperties().getOutputSet());
- hyperGraph.buildDPhyperGraph(group.getLogicalExpressions().get(0));
- return hyperGraph;
- }
-
- // Build Graph for DPhyper
- private Pair<BitSet, Long> buildDPhyperGraph(GroupExpression
groupExpression) {
- // process Project
- if (isValidProject(groupExpression.getPlan())) {
- LogicalProject<?> project = (LogicalProject<?>)
groupExpression.getPlan();
- Pair<BitSet, Long> res =
this.buildDPhyperGraph(groupExpression.child(0).getLogicalExpressions().get(0));
- for (NamedExpression expr : project.getProjects()) {
- if (expr instanceof Alias) {
- this.addAlias((Alias) expr, res.second);
- }
- }
- return res;
+ /**
+ * Graph simplifier need to update the edge for join ordering
+ *
+ * @param edgeIndex The index of updated edge
+ * @param newLeft The new left of updated edge
+ * @param newRight The new right of update edge
+ */
+ public void modifyEdge(int edgeIndex, long newLeft, long newRight) {
+ // When modify an edge in hyper graph, we need to update the left and
right nodes
+ // For these nodes that are only in the old edge, we need remove the
edge from them
+ // For these nodes that are only in the new edge, we need to add the
edge to them
+ Edge edge = joinEdges.get(edgeIndex);
+ if (treeEdgesCache.containsKey(edge.getReferenceNodes())) {
+ treeEdgesCache.get(edge.getReferenceNodes()).set(edgeIndex, false);
}
-
- // process Join
- if (isValidJoin(groupExpression.getPlan())) {
- LogicalJoin<?, ?> join = (LogicalJoin<?, ?>)
groupExpression.getPlan();
- Pair<BitSet, Long> left =
this.buildDPhyperGraph(groupExpression.child(0).getLogicalExpressions().get(0));
- Pair<BitSet, Long> right =
this.buildDPhyperGraph(groupExpression.child(1).getLogicalExpressions().get(0));
- return Pair.of(this.addJoin(join, left, right),
- LongBitmap.or(left.second, right.second));
+ updateEdges(edge, edge.getLeftExtendedNodes(), newLeft);
+ updateEdges(edge, edge.getRightExtendedNodes(), newRight);
+ joinEdges.get(edgeIndex).setLeftExtendedNodes(newLeft);
+ joinEdges.get(edgeIndex).setRightExtendedNodes(newRight);
+ if (treeEdgesCache.containsKey(edge.getReferenceNodes())) {
+ treeEdgesCache.get(edge.getReferenceNodes()).set(edgeIndex, true);
}
-
- // process Other Node
- int idx = this.addDPHyperNode(groupExpression.getOwnerGroup());
- return Pair.of(new BitSet(), LongBitmap.newBitmap(idx));
- }
-
- private void addStructInfo(HyperGraph other) {
- int offset = this.getNodes().size();
- other.getNodes().forEach(n -> this.addStructInfoNode(n.getPlan()));
- other.getComplexProject().forEach((t, projectList) ->
- projectList.forEach(e -> this.addAlias((Alias) e, t <<
offset)));
- other.getJoinEdges().forEach(this::addEdgeOfInfo);
}
- // Build Graph for matching mv, return join edge set and nodes in this plan
- private Pair<BitSet, Long> buildStructInfo(Plan plan) {
- if (plan instanceof GroupPlan) {
- Group group = ((GroupPlan) plan).getGroup();
- List<HyperGraph> childGraphs = ((GroupPlan)
plan).getGroup().getHyperGraphs();
- if (childGraphs.size() != 0) {
- int idx = addStructInfoNode(childGraphs);
- return Pair.of(new BitSet(), LongBitmap.newBitmap(idx));
- }
- GroupExpression groupExpression =
group.getLogicalExpressions().get(0);
- return buildStructInfo(groupExpression.getPlan()
- .withChildren(
-
groupExpression.children().stream().map(GroupPlan::new).collect(Collectors.toList())));
- }
- // process Project
- if (isValidProject(plan)) {
- LogicalProject<?> project = (LogicalProject<?>) plan;
- Pair<BitSet, Long> res = this.buildStructInfo(plan.child(0));
- for (NamedExpression expr : project.getProjects()) {
- if (expr instanceof Alias) {
- this.addAlias((Alias) expr, res.second);
- }
- }
- return res;
- }
-
- // process Join
- if (isValidJoinForStructInfo(plan)) {
- LogicalJoin<?, ?> join = (LogicalJoin<?, ?>) plan;
- Pair<BitSet, Long> left = this.buildStructInfo(plan.child(0));
- Pair<BitSet, Long> right = this.buildStructInfo(plan.child(1));
- return Pair.of(this.addJoin(join, left, right),
- LongBitmap.or(left.second, right.second));
- }
-
- if (isValidFilter(plan)) {
- LogicalFilter<?> filter = (LogicalFilter<?>) plan;
- Pair<BitSet, Long> child = this.buildStructInfo(filter.child());
- this.addFilter(filter, child);
- return Pair.of(new BitSet(), child.second);
- }
-
- // process Other Node
- int idx = this.addStructInfoNode(plan);
- return Pair.of(new BitSet(), LongBitmap.newBitmap(idx));
- }
+ private void updateEdges(Edge edge, long oldNodes, long newNodes) {
+ long removeNodes = LongBitmap.newBitmapDiff(oldNodes, newNodes);
+ LongBitmap.getIterator(removeNodes).forEach(index ->
nodes.get(index).removeEdge(edge));
- /**
- * inner join group without mark slot
- */
- public static boolean isValidJoin(Plan plan) {
- if (!(plan instanceof LogicalJoin)) {
- return false;
- }
- LogicalJoin<?, ?> join = (LogicalJoin<?, ?>) plan;
- return join.getJoinType() == JoinType.INNER_JOIN
- && !join.isMarkJoin()
- && !join.getExpressions().isEmpty();
+ long addedNodes = LongBitmap.newBitmapDiff(newNodes, oldNodes);
+ LongBitmap.getIterator(addedNodes).forEach(index ->
nodes.get(index).attachEdge(edge));
}
/**
@@ -489,39 +198,16 @@ public class HyperGraph {
}
/**
- * Graph simplifier need to update the edge for join ordering
- *
- * @param edgeIndex The index of updated edge
- * @param newLeft The new left of updated edge
- * @param newRight The new right of update edge
+ * inner join group without mark slot
*/
- public void modifyEdge(int edgeIndex, long newLeft, long newRight) {
- // When modify an edge in hyper graph, we need to update the left and
right nodes
- // For these nodes that are only in the old edge, we need remove the
edge from them
- // For these nodes that are only in the new edge, we need to add the
edge to them
- Edge edge = joinEdges.get(edgeIndex);
- if (treeEdgesCache.containsKey(edge.getReferenceNodes())) {
- treeEdgesCache.get(edge.getReferenceNodes()).set(edgeIndex, false);
- }
- updateEdges(edge, edge.getLeftExtendedNodes(), newLeft);
- updateEdges(edge, edge.getRightExtendedNodes(), newRight);
- joinEdges.get(edgeIndex).setLeftExtendedNodes(newLeft);
- joinEdges.get(edgeIndex).setRightExtendedNodes(newRight);
- if (treeEdgesCache.containsKey(edge.getReferenceNodes())) {
- treeEdgesCache.get(edge.getReferenceNodes()).set(edgeIndex, true);
+ public static boolean isValidJoin(Plan plan) {
+ if (!(plan instanceof LogicalJoin)) {
+ return false;
}
- }
-
- private void updateEdges(Edge edge, long oldNodes, long newNodes) {
- long removeNodes = LongBitmap.newBitmapDiff(oldNodes, newNodes);
- LongBitmap.getIterator(removeNodes).forEach(index ->
nodes.get(index).removeEdge(edge));
-
- long addedNodes = LongBitmap.newBitmapDiff(newNodes, oldNodes);
- LongBitmap.getIterator(addedNodes).forEach(index ->
nodes.get(index).attachEdge(edge));
- }
-
- public int edgeSize() {
- return joinEdges.size() + filterEdges.size();
+ LogicalJoin<?, ?> join = (LogicalJoin<?, ?>) plan;
+ return join.getJoinType() == JoinType.INNER_JOIN
+ && !join.isMarkJoin()
+ && !join.getExpressions().isEmpty();
}
/**
@@ -535,7 +221,7 @@ public class HyperGraph {
*/
public String toDottyHyperGraph() {
StringBuilder builder = new StringBuilder();
- builder.append(String.format("digraph G { # %d edges\n",
joinEdges.size()));
+ builder.append(String.format("digraph G { # %d edges%n",
joinEdges.size()));
List<String> graphvisNodes = new ArrayList<>();
for (AbstractNode node : nodes) {
String nodeName = node.getName();
@@ -547,7 +233,7 @@ public class HyperGraph {
double rowCount = (node instanceof DPhyperNode)
? ((DPhyperNode) node).getRowCount()
: -1;
- builder.append(String.format(" %s [label=\"%s \n
rowCount=%.2f\"];\n",
+ builder.append(String.format(" %s [label=\"%s %n
rowCount=%.2f\"];%n",
nodeID, nodeName, rowCount));
graphvisNodes.add(nodeName);
}
@@ -563,11 +249,11 @@ public class HyperGraph {
int leftIndex =
LongBitmap.lowestOneIndex(edge.getLeftExtendedNodes());
int rightIndex =
LongBitmap.lowestOneIndex(edge.getRightExtendedNodes());
- builder.append(String.format("%s -> %s [label=\"%s\"%s]\n",
graphvisNodes.get(leftIndex),
+ builder.append(String.format("%s -> %s [label=\"%s\"%s]%n",
graphvisNodes.get(leftIndex),
graphvisNodes.get(rightIndex), label, arrowHead));
} else {
// Hyper edge is considered as a tiny virtual node
- builder.append(String.format("e%d [shape=circle, width=.001,
label=\"\"]\n", i));
+ builder.append(String.format("e%d [shape=circle, width=.001,
label=\"\"]%n", i));
String leftLabel = "";
String rightLabel = "";
@@ -577,21 +263,312 @@ public class HyperGraph {
leftLabel = label;
}
- int finalI = i;
String finalLeftLabel = leftLabel;
for (int nodeIndex :
LongBitmap.getIterator(edge.getLeftExtendedNodes())) {
- builder.append(String.format("%s -> e%d [arrowhead=none,
label=\"%s\"]\n",
- graphvisNodes.get(nodeIndex), finalI,
finalLeftLabel));
+ builder.append(String.format("%s -> e%d [arrowhead=none,
label=\"%s\"]%n",
+ graphvisNodes.get(nodeIndex), i, finalLeftLabel));
}
String finalRightLabel = rightLabel;
for (int nodeIndex :
LongBitmap.getIterator(edge.getRightExtendedNodes())) {
- builder.append(String.format("%s -> e%d [arrowhead=none,
label=\"%s\"]\n",
- graphvisNodes.get(nodeIndex), finalI,
finalRightLabel));
+ builder.append(String.format("%s -> e%d [arrowhead=none,
label=\"%s\"]%n",
+ graphvisNodes.get(nodeIndex), i, finalRightLabel));
}
}
}
builder.append("}\n");
return builder.toString();
}
+
+ public static HyperGraph.Builder builderForDPhyper(Group group) {
+ return new HyperGraph.Builder().buildHyperGraphForDPhyper(group);
+ }
+
+ public static HyperGraph.Builder builderForMv(Plan plan) {
+ return new HyperGraph.Builder().buildHyperGraphForMv(plan);
+ }
+
+ /**
+ * Builder of HyperGraph
+ */
+ public static class Builder {
+ private final List<JoinEdge> joinEdges = new ArrayList<>();
+ private final List<FilterEdge> filterEdges = new ArrayList<>();
+ private final List<AbstractNode> nodes = new ArrayList<>();
+
+ // These hyperGraphs should be replaced nodes when building all
+ private final Map<Long, List<HyperGraph>> replacedHyperGraphs = new
HashMap<>();
+ private final HashMap<Slot, Long> slotToNodeMap = new HashMap<>();
+ private final Map<Long, List<NamedExpression>> complexProject = new
HashMap<>();
+ private Set<Slot> finalOutputs;
+
+ public List<AbstractNode> getNodes() {
+ return nodes;
+ }
+
+ private HyperGraph.Builder buildHyperGraphForDPhyper(Group group) {
+ finalOutputs = group.getLogicalProperties().getOutputSet();
+ this.buildForDPhyper(group.getLogicalExpression());
+ return this;
+ }
+
+ private HyperGraph.Builder buildHyperGraphForMv(Plan plan) {
+ finalOutputs = plan.getOutputSet();
+ this.buildForMv(plan);
+ return this;
+ }
+
+ public HyperGraph build() {
+ return new HyperGraph(finalOutputs, joinEdges, nodes, filterEdges,
complexProject);
+ }
+
+ public List<HyperGraph> buildAll() {
+ return ImmutableList.of(build());
+ }
+
+ public void updateNode(int idx, Group group) {
+ Preconditions.checkArgument(nodes.get(idx) instanceof DPhyperNode);
+ nodes.set(idx, ((DPhyperNode) nodes.get(idx)).withGroup(group));
+ }
+
+ // Build Graph for DPhyper
+ private Pair<BitSet, Long> buildForDPhyper(GroupExpression
groupExpression) {
+ // process Project
+ if (isValidProject(groupExpression.getPlan())) {
+ LogicalProject<?> project = (LogicalProject<?>)
groupExpression.getPlan();
+ Pair<BitSet, Long> res =
this.buildForDPhyper(groupExpression.child(0).getLogicalExpressions().get(0));
+ for (NamedExpression expr : project.getProjects()) {
+ if (expr instanceof Alias) {
+ this.addAlias((Alias) expr, res.second);
+ }
+ }
+ return res;
+ }
+
+ // process Join
+ if (isValidJoin(groupExpression.getPlan())) {
+ LogicalJoin<?, ?> join = (LogicalJoin<?, ?>)
groupExpression.getPlan();
+ Pair<BitSet, Long> left =
+
this.buildForDPhyper(groupExpression.child(0).getLogicalExpressions().get(0));
+ Pair<BitSet, Long> right =
+
this.buildForDPhyper(groupExpression.child(1).getLogicalExpressions().get(0));
+ return Pair.of(this.addJoin(join, left, right),
+ LongBitmap.or(left.second, right.second));
+ }
+
+ // process Other Node
+ int idx = this.addDPHyperNode(groupExpression.getOwnerGroup());
+ return Pair.of(new BitSet(), LongBitmap.newBitmap(idx));
+ }
+
+ // Build Graph for matching mv, return join edge set and nodes in this
plan
+ private Pair<BitSet, Long> buildForMv(Plan plan) {
+ if (plan instanceof GroupPlan) {
+ Group group = ((GroupPlan) plan).getGroup();
+ GroupExpression groupExpression =
group.getLogicalExpressions().get(0);
+ return buildForMv(groupExpression.getPlan()
+ .withChildren(
+
groupExpression.children().stream().map(GroupPlan::new).collect(Collectors.toList())));
+ }
+ // process Project
+ if (isValidProject(plan)) {
+ LogicalProject<?> project = (LogicalProject<?>) plan;
+ Pair<BitSet, Long> res = this.buildForMv(plan.child(0));
+ for (NamedExpression expr : project.getProjects()) {
+ if (expr instanceof Alias) {
+ this.addAlias((Alias) expr, res.second);
+ }
+ }
+ return res;
+ }
+
+ // process Join
+ if (isValidJoinForStructInfo(plan)) {
+ LogicalJoin<?, ?> join = (LogicalJoin<?, ?>) plan;
+ Pair<BitSet, Long> left = this.buildForMv(plan.child(0));
+ Pair<BitSet, Long> right = this.buildForMv(plan.child(1));
+ return Pair.of(this.addJoin(join, left, right),
+ LongBitmap.or(left.second, right.second));
+ }
+
+ if (isValidFilter(plan)) {
+ LogicalFilter<?> filter = (LogicalFilter<?>) plan;
+ Pair<BitSet, Long> child = this.buildForMv(filter.child());
+ this.addFilter(filter, child);
+ return Pair.of(new BitSet(), child.second);
+ }
+
+ // process Other Node
+ int idx = this.addStructInfoNode(plan);
+ return Pair.of(new BitSet(), LongBitmap.newBitmap(idx));
+ }
+
+ /**
+ * Store the relation between Alias Slot and Original Slot and its
expression
+ * e.g.,
+ * a = b
+ * |--- project((c + d) as b)
+ * <p>
+ * a = b
+ * |--- project((c + 1) as b)
+ *
+ * @param alias The alias Expression in project Operator
+ */
+ public boolean addAlias(Alias alias, long subTreeNodes) {
+ Slot aliasSlot = alias.toSlot();
+ if (slotToNodeMap.containsKey(aliasSlot)) {
+ return true;
+ }
+ long bitmap = LongBitmap.newBitmap();
+ for (Slot slot : alias.getInputSlots()) {
+ bitmap = LongBitmap.or(bitmap, slotToNodeMap.get(slot));
+ }
+ // The case hit when there are some constant aliases such as:
+ // select * from t1 join (
+ // select *, 1 as b1 from t2)
+ // on t1.b = b1
+ // just reference them all for this slot
+ if (bitmap == 0) {
+ bitmap = subTreeNodes;
+ }
+ Preconditions.checkArgument(bitmap > 0, "slot must belong to some
table");
+ slotToNodeMap.put(aliasSlot, bitmap);
+ if (!complexProject.containsKey(bitmap)) {
+ complexProject.put(bitmap, new ArrayList<>());
+ }
+ alias = (Alias)
PlanUtils.mergeProjections(complexProject.get(bitmap),
Lists.newArrayList(alias)).get(0);
+
+ complexProject.get(bitmap).add(alias);
+ return true;
+ }
+
+ /**
+ * add end node to HyperGraph
+ *
+ * @param group The group that is the end node in graph
+ * @return return the node index
+ */
+ private int addDPHyperNode(Group group) {
+ for (Slot slot :
group.getLogicalExpression().getPlan().getOutput()) {
+ Preconditions.checkArgument(!slotToNodeMap.containsKey(slot));
+ slotToNodeMap.put(slot, LongBitmap.newBitmap(nodes.size()));
+ }
+ nodes.add(new DPhyperNode(nodes.size(), group));
+ return nodes.size() - 1;
+ }
+
+ /**
+ * add end node to HyperGraph
+ *
+ * @param plan The plan that is the end node in graph
+ * @return return the node index
+ */
+ private int addStructInfoNode(Plan plan) {
+ for (Slot slot : plan.getOutput()) {
+ Preconditions.checkArgument(!slotToNodeMap.containsKey(slot));
+ slotToNodeMap.put(slot, LongBitmap.newBitmap(nodes.size()));
+ }
+ nodes.add(new StructInfoNode(nodes.size(), plan));
+ return nodes.size() - 1;
+ }
+
+ private long calNodeMap(Set<Slot> slots) {
+ Preconditions.checkArgument(slots.size() != 0);
+ long bitmap = LongBitmap.newBitmap();
+ for (Slot slot : slots) {
+ Preconditions.checkArgument(slotToNodeMap.containsKey(slot));
+ bitmap = LongBitmap.or(bitmap, slotToNodeMap.get(slot));
+ }
+ return bitmap;
+ }
+
+ /**
+ * try to add edge for join group
+ *
+ * @param join The join plan
+ */
+ private BitSet addJoin(LogicalJoin<?, ?> join,
+ Pair<BitSet, Long> leftEdgeNodes, Pair<BitSet, Long>
rightEdgeNodes) {
+ HashMap<Pair<Long, Long>, Pair<List<Expression>,
List<Expression>>> conjuncts = new HashMap<>();
+ for (Expression expression : join.getHashJoinConjuncts()) {
+ // TODO: avoid calling calculateEnds if calNodeMap's results
are same
+ Pair<Long, Long> ends =
calculateEnds(calNodeMap(expression.getInputSlots()), leftEdgeNodes,
+ rightEdgeNodes);
+ if (!conjuncts.containsKey(ends)) {
+ conjuncts.put(ends, Pair.of(new ArrayList<>(), new
ArrayList<>()));
+ }
+ conjuncts.get(ends).first.add(expression);
+ }
+ for (Expression expression : join.getOtherJoinConjuncts()) {
+ Pair<Long, Long> ends =
calculateEnds(calNodeMap(expression.getInputSlots()), leftEdgeNodes,
+ rightEdgeNodes);
+ if (!conjuncts.containsKey(ends)) {
+ conjuncts.put(ends, Pair.of(new ArrayList<>(), new
ArrayList<>()));
+ }
+ conjuncts.get(ends).second.add(expression);
+ }
+
+ BitSet curJoinEdges = new BitSet();
+ for (Map.Entry<Pair<Long, Long>, Pair<List<Expression>,
List<Expression>>> entry : conjuncts
+ .entrySet()) {
+ LogicalJoin<?, ?> singleJoin = new
LogicalJoin<>(join.getJoinType(), entry.getValue().first,
+ entry.getValue().second,
+ new DistributeHint(DistributeType.NONE),
join.getMarkJoinSlotReference(),
+ Lists.newArrayList(join.left(), join.right()));
+ Pair<Long, Long> ends = entry.getKey();
+ JoinEdge edge = new JoinEdge(singleJoin, joinEdges.size(),
leftEdgeNodes.first, rightEdgeNodes.first,
+ LongBitmap.newBitmapUnion(leftEdgeNodes.second,
rightEdgeNodes.second),
+ ends.first, ends.second);
+ for (int nodeIndex :
LongBitmap.getIterator(edge.getReferenceNodes())) {
+ nodes.get(nodeIndex).attachEdge(edge);
+ }
+ curJoinEdges.set(edge.getIndex());
+ joinEdges.add(edge);
+ }
+ curJoinEdges.stream().forEach(i ->
joinEdges.get(i).addCurJoinEdges(curJoinEdges));
+ curJoinEdges.stream().forEach(i ->
ConflictRulesMaker.makeJoinConflictRules(joinEdges.get(i), joinEdges));
+ curJoinEdges.stream().forEach(i ->
+
ConflictRulesMaker.makeFilterConflictRules(joinEdges.get(i), joinEdges,
filterEdges));
+ return curJoinEdges;
+ // In MySQL, each edge is reversed and store in edges again for
reducing the branch miss
+ // We don't implement this trick now.
+ }
+
+ private BitSet addFilter(LogicalFilter<?> filter, Pair<BitSet, Long>
childEdgeNodes) {
+ FilterEdge edge = new FilterEdge(filter, filterEdges.size(),
childEdgeNodes.first, childEdgeNodes.second,
+ childEdgeNodes.second);
+ filterEdges.add(edge);
+ BitSet bitSet = new BitSet();
+ bitSet.set(edge.getIndex());
+ return bitSet;
+ }
+
+ // Try to calculate the ends of an expression.
+ // left = ref_nodes \cap left_tree , right = ref_nodes \cap right_tree
+ // if left = 0, recursively calculate it in left tree
+ private Pair<Long, Long> calculateEnds(long allNodes, Pair<BitSet,
Long> leftEdgeNodes,
+ Pair<BitSet, Long> rightEdgeNodes) {
+ long left = LongBitmap.newBitmapIntersect(allNodes,
leftEdgeNodes.second);
+ long right = LongBitmap.newBitmapIntersect(allNodes,
rightEdgeNodes.second);
+ if (left == 0) {
+ Preconditions.checkArgument(leftEdgeNodes.first.cardinality()
> 0,
+ "the number of the table which expression reference is
less 2");
+ Pair<BitSet, Long> llEdgesNodes =
joinEdges.get(leftEdgeNodes.first.nextSetBit(0)).getLeftEdgeNodes(
+ joinEdges);
+ Pair<BitSet, Long> lrEdgesNodes =
joinEdges.get(leftEdgeNodes.first.nextSetBit(0)).getRightEdgeNodes(
+ joinEdges);
+ return calculateEnds(allNodes, llEdgesNodes, lrEdgesNodes);
+ }
+ if (right == 0) {
+ Preconditions.checkArgument(rightEdgeNodes.first.cardinality()
> 0,
+ "the number of the table which expression reference is
less 2");
+ Pair<BitSet, Long> rlEdgesNodes =
joinEdges.get(rightEdgeNodes.first.nextSetBit(0)).getLeftEdgeNodes(
+ joinEdges);
+ Pair<BitSet, Long> rrEdgesNodes =
joinEdges.get(rightEdgeNodes.first.nextSetBit(0)).getRightEdgeNodes(
+ joinEdges);
+ return calculateEnds(allNodes, rlEdgesNodes, rrEdgesNodes);
+ }
+ return Pair.of(left, right);
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/node/StructInfoNode.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/node/StructInfoNode.java
index 9e3886bfdca..e32baba6a58 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/node/StructInfoNode.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/node/StructInfoNode.java
@@ -17,7 +17,6 @@
package org.apache.doris.nereids.jobs.joinorder.hypergraph.node;
-import org.apache.doris.nereids.jobs.joinorder.hypergraph.HyperGraph;
import org.apache.doris.nereids.jobs.joinorder.hypergraph.edge.Edge;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.plans.GroupPlan;
@@ -44,8 +43,6 @@ import javax.annotation.Nullable;
* HyperGraph Node.
*/
public class StructInfoNode extends AbstractNode {
-
- private List<HyperGraph> graphs = new ArrayList<>();
private final List<Set<Expression>> expressions;
private final Set<CatalogRelation> relationSet;
@@ -59,11 +56,6 @@ public class StructInfoNode extends AbstractNode {
this(index, plan, new ArrayList<>());
}
- public StructInfoNode(int index, List<HyperGraph> graphs) {
- this(index, graphs.get(0).getNode(0).getPlan(), new ArrayList<>());
- this.graphs = graphs;
- }
-
private @Nullable List<Set<Expression>> collectExpressions(Plan plan) {
if (plan instanceof LeafPlan) {
return ImmutableList.of();
@@ -122,14 +114,6 @@ public class StructInfoNode extends AbstractNode {
return plan.withChildren(children);
}
- public boolean needToFlat() {
- return !graphs.isEmpty();
- }
-
- public List<HyperGraph> getGraphs() {
- return graphs;
- }
-
@Override
public String toString() {
return Utils.toSqlString("StructInfoNode[" + this.getName() + "]",
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
index 3451d8e7c44..62f325a05d4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
@@ -225,7 +225,7 @@ public class StructInfo {
// if single table without join, the bottom is
originalPlan.accept(PLAN_SPLITTER, planSplitContext);
- List<HyperGraph> structInfos =
HyperGraph.toStructInfo(planSplitContext.getBottomPlan());
+ List<HyperGraph> structInfos =
HyperGraph.builderForMv(planSplitContext.getBottomPlan()).buildAll();
return structInfos.stream()
.map(hyperGraph -> StructInfo.of(originalPlan,
planSplitContext.getTopPlan(),
planSplitContext.getBottomPlan(), hyperGraph))
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
index bbf7746ec6a..afdce7ca08d 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
@@ -63,8 +63,8 @@ class CompareOuterJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
Assertions.assertFalse(
HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2)).isInvalid());
}
@@ -82,8 +82,8 @@ class CompareOuterJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
Assertions.assertFalse(
HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2)).isInvalid());
}
@@ -108,8 +108,8 @@ class CompareOuterJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertEquals(1, res.getQueryExpressions().size());
Assertions.assertEquals("(id = 0)",
res.getQueryExpressions().get(0).toSql());
@@ -135,8 +135,8 @@ class CompareOuterJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
List<Expression> exprList = HyperGraphComparator.isLogicCompatible(h1,
h2, constructContext(p1, p2)).getQueryExpressions();
Assertions.assertEquals(0, exprList.size());
}
@@ -162,8 +162,8 @@ class CompareOuterJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertEquals(1, res.getQueryExpressions().size());
Assertions.assertEquals("(id = 0)",
res.getQueryExpressions().get(0).toSql());
@@ -190,8 +190,8 @@ class CompareOuterJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(res.isInvalid());
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferJoinTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferJoinTest.java
index 3f1ce3fc345..05f56c4de20 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferJoinTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferJoinTest.java
@@ -58,8 +58,8 @@ class InferJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertFalse(res.isInvalid());
Assertions.assertEquals(1, res.getViewNoNullableSlot().size());
@@ -87,8 +87,8 @@ class InferJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertFalse(res.isInvalid());
Assertions.assertEquals(1, res.getViewNoNullableSlot().size());
@@ -124,8 +124,8 @@ class InferJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertFalse(res.isInvalid());
Assertions.assertEquals(1, res.getViewNoNullableSlot().size());
@@ -155,8 +155,8 @@ class InferJoinTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(res.isInvalid());
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferPredicateTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferPredicateTest.java
index 5ea49a51f5c..8bb1ede8048 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferPredicateTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/InferPredicateTest.java
@@ -53,8 +53,8 @@ class InferPredicateTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertFalse(res.isInvalid());
Assertions.assertEquals("(id = 1)",
res.getQueryExpressions().get(0).toSql());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/PullupExpressionTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/PullupExpressionTest.java
index 44b60753947..6e65dba4f03 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/PullupExpressionTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/PullupExpressionTest.java
@@ -53,8 +53,8 @@ class PullupExpressionTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertEquals(1, res.getQueryExpressions().size());
Assertions.assertEquals("(id = 1)",
res.getQueryExpressions().get(0).toSql());
@@ -79,8 +79,8 @@ class PullupExpressionTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertEquals(1, res.getQueryExpressions().size());
Assertions.assertEquals("(score = score)",
res.getQueryExpressions().get(0).toSql());
@@ -105,8 +105,8 @@ class PullupExpressionTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertEquals(2, res.getViewExpressions().size());
Assertions.assertEquals("(id = 1)",
res.getViewExpressions().get(0).toSql());
@@ -132,8 +132,8 @@ class PullupExpressionTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertEquals(1, res.getViewExpressions().size());
Assertions.assertEquals("(score = score)",
res.getViewExpressions().get(0).toSql());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/BuildStructInfoTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/BuildStructInfoTest.java
index bf5edfa45ec..20324ff8739 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/BuildStructInfoTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/BuildStructInfoTest.java
@@ -41,7 +41,7 @@ class BuildStructInfoTest extends SqlTestBase {
.deriveStats()
.matches(logicalJoin()
.when(j -> {
- HyperGraph.toStructInfo(j);
+ HyperGraph.builderForMv(j);
return true;
}));
@@ -58,7 +58,7 @@ class BuildStructInfoTest extends SqlTestBase {
.deriveStats()
.matches(logicalJoin()
.when(j -> {
- List<HyperGraph> hyperGraph =
HyperGraph.toStructInfo(j);
+ List<HyperGraph> hyperGraph =
HyperGraph.builderForMv(j).buildAll();
Assertions.assertTrue(hyperGraph.get(0).getNodes().stream()
.allMatch(n -> n.getPlan()
.collectToList(GroupPlan.class::isInstance).isEmpty()));
@@ -77,7 +77,7 @@ class BuildStructInfoTest extends SqlTestBase {
.rewrite()
.matches(logicalJoin()
.when(j -> {
- HyperGraph structInfo =
HyperGraph.toStructInfo(j).get(0);
+ HyperGraph structInfo =
HyperGraph.builderForMv(j).buildAll().get(0);
Assertions.assertTrue(structInfo.getJoinEdge(0).getJoinType().isLeftOuterJoin());
Assertions.assertEquals(0,
structInfo.getFilterEdge(0).getLeftRejectEdge().size());
Assertions.assertEquals(1,
structInfo.getFilterEdge(0).getRightRejectEdge().size());
@@ -91,7 +91,7 @@ class BuildStructInfoTest extends SqlTestBase {
.rewrite()
.matches(logicalJoin()
.when(j -> {
- HyperGraph structInfo =
HyperGraph.toStructInfo(j).get(0);
+ HyperGraph structInfo =
HyperGraph.builderForMv(j).buildAll().get(0);
Assertions.assertTrue(structInfo.getJoinEdge(0).getJoinType().isLeftOuterJoin());
return true;
}));
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphAggTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphAggTest.java
index 6032d000407..38ebc99c479 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphAggTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphAggTest.java
@@ -49,7 +49,7 @@ class HyperGraphAggTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p2).buildAll().get(0);
Assertions.assertEquals("id", Objects.requireNonNull(((StructInfoNode)
h1.getNode(1)).getExpressions()).get(0).toSql());
}
@@ -79,8 +79,8 @@ class HyperGraphAggTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(!res.isInvalid());
Assertions.assertEquals(2, res.getViewNoNullableSlot().size());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparatorTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparatorTest.java
index b89934d4577..1fd2ac86ab6 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparatorTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparatorTest.java
@@ -55,8 +55,8 @@ class HyperGraphComparatorTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(!res.isInvalid());
Assertions.assertEquals(2, res.getViewNoNullableSlot().size());
@@ -86,8 +86,8 @@ class HyperGraphComparatorTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(!res.isInvalid());
Assertions.assertEquals(2, res.getViewNoNullableSlot().size());
@@ -118,8 +118,8 @@ class HyperGraphComparatorTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(!res.isInvalid());
Assertions.assertEquals(2, res.getViewNoNullableSlot().size());
@@ -153,8 +153,8 @@ class HyperGraphComparatorTest extends SqlTestBase {
.rewrite()
.applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
.getAllPlan().get(0).child(0);
- HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
- HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+ HyperGraph h1 = HyperGraph.builderForMv(p1).buildAll().get(0);
+ HyperGraph h2 = HyperGraph.builderForMv(p2).buildAll().get(0);
ComparisonResult res = HyperGraphComparator.isLogicCompatible(h1, h2,
constructContext(p1, p2));
Assertions.assertTrue(!res.isInvalid());
Assertions.assertEquals(2, res.getViewNoNullableSlot().size());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/HyperGraphBuilder.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/HyperGraphBuilder.java
index f544e6ad8b1..d167054c29f 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/HyperGraphBuilder.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/HyperGraphBuilder.java
@@ -335,14 +335,14 @@ public class HyperGraphBuilder {
plan);
cascadesContext.getJobScheduler().executeJobPool(cascadesContext);
injectRowcount(cascadesContext.getMemo().getRoot());
- return HyperGraph.toDPhyperGraph(cascadesContext.getMemo().getRoot());
+ return
HyperGraph.builderForDPhyper(cascadesContext.getMemo().getRoot()).build();
}
public static HyperGraph buildHyperGraphFromPlan(Plan plan) {
CascadesContext cascadesContext =
MemoTestUtils.createCascadesContext(MemoTestUtils.createConnectContext(),
plan);
cascadesContext.getJobScheduler().executeJobPool(cascadesContext);
- return HyperGraph.toDPhyperGraph(cascadesContext.getMemo().getRoot());
+ return
HyperGraph.builderForDPhyper(cascadesContext.getMemo().getRoot()).build();
}
private void injectRowcount(Group group) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]