Skip to content

Commit

Permalink
[opt](mtmv) Materialized view partition track supports date_trunc and…
Browse files Browse the repository at this point in the history
… optimize the fail reason (apache#35562)

this depends on apache#34781

1. Materialized view partition track supports date_trunc and optimize the fail reason.

2. it supports create partition mv as following:
this mv will be partition updated by day

CREATE MATERIALIZED VIEW mv_6
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
partition by(date_trunc(date_alias, 'day'))
DISTRIBUTED BY RANDOM BUCKETS 2
PROPERTIES ('replication_num' = '1')
AS
SELECT date_trunc(t1.L_SHIPDATE, 'hour') as date_alias, t2.O_ORDERDATE, t1.L_QUANTITY, t2.O_ORDERSTATUS, 
count(distinct case when t1.L_SUPPKEY > 0 then t2.O_ORDERSTATUS else null end) as cnt_1 
from 
  (select * from 
  lineitem 
  where L_SHIPDATE in ('2017-01-30')) t1 
left join 
  (select * from 
  orders 
  where O_ORDERDATE in ('2017-01-30')) t2 
on t1.L_ORDERKEY = t2.O_ORDERKEY 
group by 
t1.L_SHIPDATE, 
t2.O_ORDERDATE, 
t1.L_QUANTITY, 
t2.O_ORDERSTATUS;
  • Loading branch information
seawinde committed Jun 20, 2024
1 parent 72f410c commit 82f4d1e
Show file tree
Hide file tree
Showing 14 changed files with 900 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import org.apache.doris.catalog.Column;
import org.apache.doris.common.AnalysisException;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.gson.annotations.SerializedName;

import java.util.List;
Expand All @@ -38,10 +36,6 @@ public enum MTMVPartitionType {
SELF_MANAGE
}

public static final ImmutableSet<String> MTMV_PARTITION_FUNCTIONS = new ImmutableSortedSet.Builder<String>(
String.CASE_INSENSITIVE_ORDER).add("date_trunc")
.build();

@SerializedName("pt")
private MTMVPartitionType partitionType;
@SerializedName("rt")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ public Optional<Pair<Id, Statistics>> getPlanStatistics(CascadesContext cascades
return Optional.empty();
}
RelationId relationId = null;
List<LogicalOlapScan> logicalOlapScan = this.getScanPlan().collectFirst(LogicalOlapScan.class::isInstance);
if (!logicalOlapScan.isEmpty()) {
relationId = logicalOlapScan.get(0).getRelationId();
Optional<LogicalOlapScan> logicalOlapScan = this.getScanPlan().collectFirst(LogicalOlapScan.class::isInstance);
if (logicalOlapScan.isPresent()) {
relationId = logicalOlapScan.get().getRelationId();
}
return Optional.of(Pair.of(relationId, normalizeStatisticsColumnExpression(mtmvCache.getStatistics())));
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
import org.apache.doris.nereids.trees.expressions.functions.agg.RollUpTrait;

import com.google.common.collect.ImmutableList;

import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -63,7 +65,8 @@ public abstract Function doRollup(
protected static List<Expression> extractArguments(Expression functionWithAny, Function actualFunction) {
Set<Object> exprSetToRemove = functionWithAny.collectToSet(expr -> !(expr instanceof Any));
return actualFunction.collectFirst(expr ->
exprSetToRemove.stream().noneMatch(exprToRemove -> exprToRemove.equals(expr)));
exprSetToRemove.stream().noneMatch(exprToRemove -> exprToRemove.equals(expr)))
.map(expr -> ImmutableList.of((Expression) expr)).orElse(ImmutableList.of());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
import org.apache.doris.nereids.rules.expression.rules.InPredicateDedup;
import org.apache.doris.nereids.rules.expression.rules.InPredicateToEqualToRule;
import org.apache.doris.nereids.rules.expression.rules.MergeDateTrunc;
import org.apache.doris.nereids.rules.expression.rules.NormalizeBinaryPredicatesRule;
import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticComparisonRule;
import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticRule;
Expand Down Expand Up @@ -53,6 +54,7 @@ public class ExpressionNormalization extends ExpressionRewrite {
DigitalMaskingConvert.INSTANCE,
SimplifyArithmeticComparisonRule.INSTANCE,
ConvertAggStateCast.INSTANCE,
MergeDateTrunc.INSTANCE,
CheckCast.INSTANCE
)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.nereids.rules.expression.rules;

import org.apache.doris.nereids.rules.expression.ExpressionPatternMatcher;
import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.scalar.DateTrunc;
import org.apache.doris.nereids.trees.expressions.literal.Interval.TimeUnit;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

import java.util.List;
import java.util.Optional;

/**
* Rewrite rule to convert
* For example:
* date_trunc(date_trunc(data_slot, 'hour'), 'day') -> date_trunc(data_slot, 'day')
*/
public class MergeDateTrunc implements ExpressionPatternRuleFactory {

public static MergeDateTrunc INSTANCE = new MergeDateTrunc();
public static ImmutableSet<TimeUnit> UN_SUPPORT_TIME_UNIT = ImmutableSet.of(TimeUnit.WEEK, TimeUnit.QUARTER);

@Override
public List<ExpressionPatternMatcher<? extends Expression>> buildRules() {
return ImmutableList.of(
matchesTopType(DateTrunc.class)
.when(dateTrunc -> dateTrunc.getArgument(0) instanceof DateTrunc)
.then(MergeDateTrunc::rewrite)
);
}

private static Expression rewrite(DateTrunc dateTrunc) {

Expression parentTimeUnitArgument = dateTrunc.getArgument(1);
if (!(parentTimeUnitArgument instanceof Literal)) {
return dateTrunc;
}
Optional<TimeUnit> parentTimeUnit = TimeUnit.of(((Literal) parentTimeUnitArgument).getStringValue());
DateTrunc childDateTrunc = (DateTrunc) dateTrunc.getArgument(0);
Expression childTimeUnitArgument = childDateTrunc.getArgument(1);
if (!(childTimeUnitArgument instanceof Literal)) {
return dateTrunc;
}
Optional<TimeUnit> childTimeUnit = TimeUnit.of(((Literal) childTimeUnitArgument).getStringValue());
if (!parentTimeUnit.isPresent() || !childTimeUnit.isPresent()) {
return dateTrunc;
}
if (UN_SUPPORT_TIME_UNIT.contains(parentTimeUnit.get())
|| UN_SUPPORT_TIME_UNIT.contains(childTimeUnit.get())) {
return dateTrunc;
}
if (parentTimeUnit.get().getLevel() < childTimeUnit.get().getLevel()) {
return dateTrunc;
}
return new DateTrunc(childDateTrunc.getArgument(0), new VarcharLiteral(parentTimeUnit.get().toString()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,15 @@ default <T> Set<T> collectToSet(Predicate<TreeNode<NODE_TYPE>> predicate) {
/**
* Collect the nodes that satisfied the predicate firstly.
*/
default <T> List<T> collectFirst(Predicate<TreeNode<NODE_TYPE>> predicate) {
default <T> Optional<T> collectFirst(Predicate<TreeNode<NODE_TYPE>> predicate) {
List<TreeNode<NODE_TYPE>> result = new ArrayList<>();
foreach(node -> {
if (result.isEmpty() && predicate.test(node)) {
result.add(node);
}
return !result.isEmpty();
});
return (List<T>) ImmutableList.copyOf(result);
return result.isEmpty() ? Optional.empty() : Optional.of((T) result.get(0));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
import org.apache.doris.nereids.types.DateType;

import com.google.common.collect.ImmutableList;
import org.apache.commons.lang3.EnumUtils;

import java.util.Optional;

/**
* Interval for timestamp calculation.
Expand Down Expand Up @@ -61,30 +64,46 @@ public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
* Supported time unit.
*/
public enum TimeUnit {
YEAR("YEAR", false),
MONTH("MONTH", false),
WEEK("WEEK", false),
DAY("DAY", false),
HOUR("HOUR", true),
MINUTE("MINUTE", true),
SECOND("SECOND", true);
YEAR("YEAR", false, 800),
MONTH("MONTH", false, 700),
QUARTER("QUARTER", false, 600),
WEEK("WEEK", false, 500),
DAY("DAY", false, 400),
HOUR("HOUR", true, 300),
MINUTE("MINUTE", true, 200),
SECOND("SECOND", true, 100);

private final String description;

private final boolean isDateTimeUnit;
/**
* Time unit level, second level is low, year level is high
*/
private final int level;

TimeUnit(String description, boolean isDateTimeUnit) {
TimeUnit(String description, boolean isDateTimeUnit, int level) {
this.description = description;
this.isDateTimeUnit = isDateTimeUnit;
this.level = level;
}

public boolean isDateTimeUnit() {
return isDateTimeUnit;
}

public int getLevel() {
return level;
}

@Override
public String toString() {
return description;
}

/**
* Construct time unit by name
*/
public static Optional<TimeUnit> of(String name) {
return Optional.ofNullable(EnumUtils.getEnumIgnoreCase(TimeUnit.class, name));
}
}
}
Loading

0 comments on commit 82f4d1e

Please sign in to comment.