This is an automated email from the ASF dual-hosted git repository.
morrysnow 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 e86c599a819 [improvement](mtmv) Optimize the nested materialized view
rewrite performance (#34050)
e86c599a819 is described below
commit e86c599a819b0aa42cf0a3d9b3e71cc128548e89
Author: seawinde <[email protected]>
AuthorDate: Wed Apr 24 18:56:36 2024 +0800
[improvement](mtmv) Optimize the nested materialized view rewrite
performance (#34050)
Optimize the nested materialized view rewrite performance when exists many
join
This is brought by #33362
---
.../java/org/apache/doris/nereids/memo/Memo.java | 4 ++
.../apache/doris/nereids/memo/StructInfoMap.java | 59 +++++++++++++++-------
.../nereids/rules/exploration/mv/StructInfo.java | 14 +++--
3 files changed, 57 insertions(+), 20 deletions(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java
index 854ff0f51cb..db12c02e79a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java
@@ -411,6 +411,9 @@ public class Memo {
Preconditions.checkState(groupExpressions.containsKey(groupExpr.get()));
return CopyInResult.of(false, groupExpr.get());
}
+ if (targetGroup != null) {
+ targetGroup.getstructInfoMap().setRefreshed(false);
+ }
List<Group> childrenGroups = Lists.newArrayList();
for (int i = 0; i < plan.children().size(); i++) {
// skip useless project.
@@ -559,6 +562,7 @@ public class Memo {
if (source == root) {
root = destination;
}
+ destination.getstructInfoMap().setRefreshed(false);
groups.remove(source.getGroupId());
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
index a14c2070a8f..4119c6f2f89 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
@@ -29,10 +29,11 @@ import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
@@ -41,6 +42,7 @@ import javax.annotation.Nullable;
public class StructInfoMap {
private final Map<BitSet, Pair<GroupExpression, List<BitSet>>>
groupExpressionMap = new HashMap<>();
private final Map<BitSet, StructInfo> infoMap = new HashMap<>();
+ private boolean refreshed;
/**
* get struct info according to table map
@@ -79,6 +81,14 @@ public class StructInfoMap {
return groupExpressionMap.get(tableMap);
}
+ public boolean isRefreshed() {
+ return refreshed;
+ }
+
+ public void setRefreshed(boolean refreshed) {
+ this.refreshed = refreshed;
+ }
+
private StructInfo constructStructInfo(GroupExpression groupExpression,
List<BitSet> children,
BitSet tableMap, Plan originPlan) {
// this plan is not origin plan, should record origin plan in struct
info
@@ -111,7 +121,7 @@ public class StructInfoMap {
int originSize = groupExpressionMap.size();
for (GroupExpression groupExpression : group.getLogicalExpressions()) {
List<Set<BitSet>> childrenTableMap = new ArrayList<>();
- boolean needRefresh = false;
+ boolean needRefresh = groupExpressionMap.isEmpty();
if (groupExpression.children().isEmpty()) {
BitSet leaf = constructLeaf(groupExpression);
groupExpressionMap.put(leaf, Pair.of(groupExpression, new
ArrayList<>()));
@@ -119,18 +129,33 @@ public class StructInfoMap {
}
for (Group child : groupExpression.children()) {
- if (!refreshedGroup.contains(child)) {
+ if (!refreshedGroup.contains(child) &&
!child.getstructInfoMap().isRefreshed()) {
StructInfoMap childStructInfoMap =
child.getstructInfoMap();
needRefresh |= childStructInfoMap.refresh(child);
+ childStructInfoMap.setRefreshed(true);
}
refreshedGroup.add(child);
childrenTableMap.add(child.getstructInfoMap().getTableMaps());
}
+ // if one same groupExpression have refreshed, continue
+ BitSet oneOfGroupExpressionTableSet = new BitSet();
+ for (Set<BitSet> groupExpressionBitSet : childrenTableMap) {
+ Iterator<BitSet> iterator = groupExpressionBitSet.iterator();
+ if (iterator.hasNext()) {
+ oneOfGroupExpressionTableSet.or(iterator.next());
+ }
+ }
+ if (groupExpressionMap.containsKey(oneOfGroupExpressionTableSet)) {
+ continue;
+ }
// if cumulative child table map is different from current
// or current group expression map is empty, should update the
groupExpressionMap currently
- Set<Pair<BitSet, List<BitSet>>> bitSetWithChildren =
cartesianProduct(childrenTableMap);
- for (Pair<BitSet, List<BitSet>> bitSetWithChild :
bitSetWithChildren) {
- groupExpressionMap.putIfAbsent(bitSetWithChild.first,
Pair.of(groupExpression, bitSetWithChild.second));
+ Collection<Pair<BitSet, List<BitSet>>> bitSetWithChildren =
cartesianProduct(childrenTableMap);
+ if (needRefresh) {
+ for (Pair<BitSet, List<BitSet>> bitSetWithChild :
bitSetWithChildren) {
+ groupExpressionMap.putIfAbsent(bitSetWithChild.first,
+ Pair.of(groupExpression, bitSetWithChild.second));
+ }
}
}
return originSize != groupExpressionMap.size();
@@ -147,17 +172,17 @@ public class StructInfoMap {
return tableMap;
}
- private Set<Pair<BitSet, List<BitSet>>> cartesianProduct(List<Set<BitSet>>
childrenTableMap) {
- return Sets.cartesianProduct(childrenTableMap)
- .stream()
- .map(bitSetList -> {
- BitSet bitSet = new BitSet();
- for (BitSet b : bitSetList) {
- bitSet.or(b);
- }
- return Pair.of(bitSet, bitSetList);
- })
- .collect(Collectors.toSet());
+ private Collection<Pair<BitSet, List<BitSet>>>
cartesianProduct(List<Set<BitSet>> childrenTableMap) {
+ Set<List<BitSet>> cartesianLists =
Sets.cartesianProduct(childrenTableMap);
+ List<Pair<BitSet, List<BitSet>>> resultPairSet = new LinkedList<>();
+ for (List<BitSet> bitSetList : cartesianLists) {
+ BitSet bitSet = new BitSet();
+ for (BitSet b : bitSetList) {
+ bitSet.or(b);
+ }
+ resultPairSet.add(Pair.of(bitSet, bitSetList));
+ }
+ return resultPairSet;
}
@Override
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 4979f11c28e..757004071ee 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
@@ -443,10 +443,18 @@ public class StructInfo {
}
}
+ /** Judge if source contains all target */
public static boolean containsAll(BitSet source, BitSet target) {
- BitSet intersection = (BitSet) source.clone();
- intersection.and(target);
- return intersection.equals(target);
+ if (source.size() < target.size()) {
+ return false;
+ }
+ for (int i = target.nextSetBit(0); i >= 0; i = target.nextSetBit(i +
1)) {
+ boolean contains = source.get(i);
+ if (!contains) {
+ return false;
+ }
+ }
+ return true;
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]