seawinde commented on code in PR #59013:
URL: https://github.com/apache/doris/pull/59013#discussion_r2644722218
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/Predicates.java:
##########
@@ -129,167 +124,179 @@ public static Map<Expression, ExpressionInfo>
compensateCouldNotPullUpPredicates
}
/**
- * compensate equivalence predicates
+ * Compensate equivalence predicates based on equivalence classes.
+ * Collects uncovered equivalence predicates into uncoveredEquals for
residual compensation.
*/
public static Map<Expression, ExpressionInfo>
compensateEquivalence(StructInfo queryStructInfo,
StructInfo viewStructInfo,
SlotMapping viewToQuerySlotMapping,
- ComparisonResult comparisonResult) {
+ ComparisonResult comparisonResult,
+ Set<Expression> uncoveredEquals) {
EquivalenceClass queryEquivalenceClass =
queryStructInfo.getEquivalenceClass();
EquivalenceClass viewEquivalenceClass =
viewStructInfo.getEquivalenceClass();
Map<SlotReference, SlotReference> viewToQuerySlotMap =
viewToQuerySlotMapping.toSlotReferenceMap();
EquivalenceClass viewEquivalenceClassQueryBased =
viewEquivalenceClass.permute(viewToQuerySlotMap);
if (viewEquivalenceClassQueryBased == null) {
return null;
}
- final Map<Expression, ExpressionInfo> equalCompensateConjunctions =
new HashMap<>();
if (queryEquivalenceClass.isEmpty() && viewEquivalenceClass.isEmpty())
{
return ImmutableMap.of();
}
- if (queryEquivalenceClass.isEmpty() &&
!viewEquivalenceClass.isEmpty()) {
- return null;
- }
EquivalenceClassMapping queryToViewEquivalenceMapping =
EquivalenceClassMapping.generate(queryEquivalenceClass,
viewEquivalenceClassQueryBased);
- // can not map all target equivalence class, can not compensate
if (queryToViewEquivalenceMapping.getEquivalenceClassSetMap().size()
< viewEquivalenceClass.getEquivalenceSetList().size()) {
return null;
}
- // do equal compensate
+ Map<Expression, ExpressionInfo> compensations = new HashMap<>();
Set<List<SlotReference>> mappedQueryEquivalenceSet =
queryToViewEquivalenceMapping.getEquivalenceClassSetMap().keySet();
for (List<SlotReference> queryEquivalenceSet :
queryEquivalenceClass.getEquivalenceSetList()) {
- // compensate the equivalence in query but not in view
if (!mappedQueryEquivalenceSet.contains(queryEquivalenceSet)) {
- Iterator<SlotReference> iterator =
queryEquivalenceSet.iterator();
- SlotReference first = iterator.next();
- while (iterator.hasNext()) {
- Expression equals = new EqualTo(first, iterator.next());
- if (equals.anyMatch(AggregateFunction.class::isInstance)) {
- return null;
- }
- equalCompensateConjunctions.put(equals,
ExpressionInfo.EMPTY);
+ SlotReference first = queryEquivalenceSet.get(0);
+ for (int i = 1; i < queryEquivalenceSet.size(); i++) {
+ uncoveredEquals.add(new EqualTo(first,
queryEquivalenceSet.get(i)));
}
} else {
- // compensate the equivalence both in query and view, but
query has more equivalence
List<SlotReference> viewEquivalenceSet =
queryToViewEquivalenceMapping.getEquivalenceClassSetMap().get(queryEquivalenceSet);
- List<SlotReference> copiedQueryEquivalenceSet = new
ArrayList<>(queryEquivalenceSet);
- copiedQueryEquivalenceSet.removeAll(viewEquivalenceSet);
- SlotReference first = viewEquivalenceSet.iterator().next();
- for (SlotReference slotReference : copiedQueryEquivalenceSet) {
- Expression equals = new EqualTo(first, slotReference);
+ List<SlotReference> queryExtraSlots = new
ArrayList<>(queryEquivalenceSet);
+ queryExtraSlots.removeAll(viewEquivalenceSet);
+
+ SlotReference firstViewSlot = viewEquivalenceSet.get(0);
+ for (SlotReference extraSlot : queryExtraSlots) {
+ Expression equals = new EqualTo(firstViewSlot, extraSlot);
if (equals.anyMatch(AggregateFunction.class::isInstance)) {
return null;
}
- equalCompensateConjunctions.put(equals,
ExpressionInfo.EMPTY);
+ compensations.put(equals, ExpressionInfo.EMPTY);
}
}
}
- return equalCompensateConjunctions;
+ return compensations;
}
/**
- * compensate range predicates
+ * Compensate range predicates.
+ * Collects uncovered range predicates into uncoveredRanges for residual
compensation.
*/
public static Map<Expression, ExpressionInfo>
compensateRangePredicate(StructInfo queryStructInfo,
StructInfo viewStructInfo,
SlotMapping viewToQuerySlotMapping,
ComparisonResult comparisonResult,
- CascadesContext cascadesContext) {
+ CascadesContext cascadesContext,
+ Set<Expression> uncoveredRanges) {
SplitPredicate querySplitPredicate =
queryStructInfo.getSplitPredicate();
SplitPredicate viewSplitPredicate = viewStructInfo.getSplitPredicate();
- Set<Expression> viewRangeQueryBasedSet = new HashSet<>();
- for (Expression viewExpression :
viewSplitPredicate.getRangePredicateMap().keySet()) {
- viewRangeQueryBasedSet.add(
- ExpressionUtils.replace(viewExpression,
viewToQuerySlotMapping.toSlotReferenceMap()));
- }
- viewRangeQueryBasedSet.remove(BooleanLiteral.TRUE);
-
- Set<Expression> queryRangeSet =
querySplitPredicate.getRangePredicateMap().keySet();
- queryRangeSet.remove(BooleanLiteral.TRUE);
+ Set<Expression> viewRangeQueryBasedSet = mapExpressionsToQueryContext(
+ viewSplitPredicate.getRangePredicateMap().keySet(),
viewToQuerySlotMapping);
+ Set<Expression> queryRangeSet = new
HashSet<>(querySplitPredicate.getRangePredicateMap().keySet());
- Set<Expression> differentExpressions = new HashSet<>();
- Sets.difference(queryRangeSet,
viewRangeQueryBasedSet).copyInto(differentExpressions);
- Sets.difference(viewRangeQueryBasedSet,
queryRangeSet).copyInto(differentExpressions);
- // the range predicate in query and view is same, don't need to
compensate
- if (differentExpressions.isEmpty()) {
- return ImmutableMap.of();
- }
- // try to normalize the different expressions
- Set<Expression> normalizedExpressions =
- normalizeExpression(ExpressionUtils.and(differentExpressions),
cascadesContext);
- if (!queryRangeSet.containsAll(normalizedExpressions)) {
- // normalized expressions is not in query, can not compensate
+ Set<Expression> mvExtraRange = Sets.difference(viewRangeQueryBasedSet,
queryRangeSet);
+ if (!mvExtraRange.isEmpty()) {
Review Comment:
If a query uses the condition a > 3, and a materialized view uses the
condition a > 1, the two conditions are combined with AND and then normalized.
If, after normalization, the resulting condition is a > 3, it proves that the
condition compensation succeeded, and this materialized view can be used for
rewriting.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]