Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,12 @@ public String getHintExplainString(List<Hint> hints) {
public String getExplainString(ExplainOptions explainOptions) {
ExplainLevel explainLevel = getExplainLevel(explainOptions);
String plan = "";
String mvSummary = "";
if (this.getPhysicalPlan() != null) {
mvSummary = "\n\n========== MATERIALIZATIONS ==========\n"
+ MaterializationContext.toSummaryString(cascadesContext.getMaterializationContexts(),
this.getPhysicalPlan());
}
switch (explainLevel) {
case PARSED_PLAN:
plan = parsedPlan.treeString();
Expand All @@ -545,22 +551,16 @@ public String getExplainString(ExplainOptions explainOptions) {
plan = rewrittenPlan.treeString();
break;
case OPTIMIZED_PLAN:
plan = "cost = " + cost + "\n" + optimizedPlan.treeString();
plan = "cost = " + cost + "\n" + optimizedPlan.treeString() + mvSummary;
break;
case SHAPE_PLAN:
plan = optimizedPlan.shape("");
break;
case MEMO_PLAN:
StringBuilder materializationStringBuilder = new StringBuilder();
materializationStringBuilder.append("materializationContexts:").append("\n");
for (MaterializationContext ctx : cascadesContext.getMaterializationContexts()) {
materializationStringBuilder.append("\n").append(ctx).append("\n");
}
plan = cascadesContext.getMemo().toString()
+ "\n\n========== OPTIMIZED PLAN ==========\n"
+ optimizedPlan.treeString()
+ "\n\n========== MATERIALIZATIONS ==========\n"
+ materializationStringBuilder;
+ mvSummary;
break;
case DISTRIBUTED_PLAN:
StringBuilder distributedPlanStringBuilder = new StringBuilder();
Expand Down Expand Up @@ -592,17 +592,18 @@ public String getExplainString(ExplainOptions explainOptions) {
+ getTimeMetricString(SummaryProfile::getPrettyNereidsDistributeTime) + " ==========\n";
plan += DistributedPlan.toString(Lists.newArrayList(distributedPlans.values())) + "\n\n";
}
plan += mvSummary;
break;
default:
plan = super.getExplainString(explainOptions)
+ MaterializationContext.toSummaryString(cascadesContext.getMaterializationContexts(),
this.getPhysicalPlan());
plan = super.getExplainString(explainOptions);
plan += mvSummary;
if (statementContext != null) {
if (statementContext.isHasUnknownColStats()) {
plan += "\n\nStatistics\n planed with unknown column statistics\n";
}
}
}

if (statementContext != null) {
if (!statementContext.getHints().isEmpty()) {
String hint = getHintExplainString(statementContext.getHints());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.doris.nereids.properties.DistributionSpecGather;
import org.apache.doris.nereids.properties.DistributionSpecHash;
import org.apache.doris.nereids.properties.DistributionSpecReplicated;
import org.apache.doris.nereids.trees.expressions.Alias;
import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.SlotReference;
Expand Down Expand Up @@ -196,6 +197,15 @@ public Cost visitPhysicalFileScan(PhysicalFileScan physicalFileScan, PlanContext

@Override
public Cost visitPhysicalProject(PhysicalProject<? extends Plan> physicalProject, PlanContext context) {
boolean trival = true;
for (Expression expr : physicalProject.getProjects()) {
if (!(expr instanceof Alias && expr.child(0) instanceof SlotReference)) {
trival = false;
}
}
if (trival) {
return CostV1.zero();
}
double exprCost = expressionTreeCost(physicalProject.getProjects());
return CostV1.ofCpu(context.getSessionVariable(), exprCost + 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ public String toString() {
builder.append("#").append(ownerGroup.getGroupId().asInt());
}
if (cost != null) {
builder.append(" cost=").append(format.format((long) cost.getValue()) + " " + cost);
builder.append(" cost=").append(cost.getValue() + " " + cost);
} else {
builder.append(" cost=null");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,10 @@ public Void visitPhysicalRelation(PhysicalRelation physicalRelation, Void contex
builder.append("\nMaterializedViewRewriteSuccessAndChose:\n");
if (!chosenMaterializationQualifiers.isEmpty()) {
chosenMaterializationQualifiers.forEach(materializationQualifier ->
builder.append(generateIdentifierName(materializationQualifier)).append(", \n"));
builder.append(" ")
.append(generateIdentifierName(materializationQualifier)).append(" chose, \n"));
} else {
builder.append(" chose: none, \n");
}
// rewrite success but not chosen
builder.append("\nMaterializedViewRewriteSuccessButNotChose:\n");
Expand All @@ -383,9 +386,11 @@ public Void visitPhysicalRelation(PhysicalRelation physicalRelation, Void contex
.filter(materializationQualifier -> !chosenMaterializationQualifiers.contains(materializationQualifier))
.collect(Collectors.toSet());
if (!rewriteSuccessButNotChoseQualifiers.isEmpty()) {
builder.append(" Names: ");
rewriteSuccessButNotChoseQualifiers.forEach(materializationQualifier ->
builder.append(generateIdentifierName(materializationQualifier)).append(", "));
builder.append(" ")
.append(generateIdentifierName(materializationQualifier)).append(" not chose, \n"));
} else {
builder.append(" not chose: none, \n");
}
// rewrite fail
builder.append("\nMaterializedViewRewriteFail:");
Expand All @@ -394,8 +399,8 @@ public Void visitPhysicalRelation(PhysicalRelation physicalRelation, Void contex
Set<String> failReasonSet =
ctx.getFailReason().values().stream().map(Pair::key).collect(ImmutableSet.toImmutableSet());
builder.append("\n")
.append(" Name: ").append(generateIdentifierName(ctx.generateMaterializationIdentifier()))
.append("\n")
.append(" ")
.append(generateIdentifierName(ctx.generateMaterializationIdentifier())).append(" fail, \n")
.append(" FailSummary: ").append(String.join(", ", failReasonSet));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,17 @@ private Statistics computeOlapScan(OlapScan olapScan) {
selectedPartitionsRowCount = tableRowCount;
}
// if estimated mv rowCount is more than actual row count, fall back to base table stats
if (selectedPartitionsRowCount > optStats.get().getRowCount()) {
return optStats.get();
if (selectedPartitionsRowCount >= optStats.get().getRowCount()) {
Statistics derivedStats = optStats.get();
double derivedRowCount = derivedStats.getRowCount();
for (Slot slot : ((Relation) olapScan).getOutput()) {
if (derivedStats.findColumnStatistics(slot) == null) {
derivedStats.addColumnStats(slot,
new ColumnStatisticBuilder(ColumnStatistic.UNKNOWN)
.setCount(derivedRowCount).build());
}
}
return derivedStats;
}
}
}
Expand Down Expand Up @@ -463,7 +472,7 @@ private Statistics computeOlapScan(OlapScan olapScan) {
}
}

if (!olapScan.getSelectedPartitionIds().isEmpty()) {
if (olapScan.getSelectedPartitionIds().size() < olapScan.getTable().getPartitionNum()) {
// partition pruned
double selectedPartitionsRowCount = getSelectedPartitionRowCount(olapScan);
if (selectedPartitionsRowCount > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public String toString() {
}
String index = "";
if (selectedIndexId != getTable().getBaseIndexId()) {
index = "(" + selectedIndexId + ")";
index = "(" + getTable().getIndexNameById(selectedIndexId) + ")";
}
String partitions = "";
int partitionCount = this.table.getPartitionNames().size();
Expand Down
27 changes: 3 additions & 24 deletions regression-test/data/mv_p0/k1s2m3/k1s2m3.out
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,20 @@
2 2 2 b
3 -3 \N c

-- !select_mv --
-- !select_mv1 --
\N \N
-4 16
1 1
2 8
3 \N

-- !select_mv --
\N \N
-4 16
1 1
2 8
3 \N

-- !select_mv --
\N \N
-4 16
1 1
2 8
3 \N

-- !select_mv --
\N \N
-4 16
1 1
2 8
3 \N

-- !select_mv --
-- !select_mv2 --
\N \N
-4 16
2 8
3 \N

-- !select_mv --
-- !select_mv6 --
0

-- !select_star --
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,6 @@
-- !sql_1 --
80000

-- !sql --
PLAN FRAGMENT 0
OUTPUT EXPRS:
sleep(100)[#0]
PARTITION: UNPARTITIONED

HAS_COLO_PLAN_NODE: false

VRESULT SINK
MYSQL_PROTOCAL

0:VUNION(32)
constant exprs:
sleep(100)

-- !sql --
true

Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ class ExplainAction implements SuiteAction {
if (!explainString.contains(string)) {
String msg = ("Explain and check failed, expect contains '${string}',"
+ " but actual explain string is:\n${explainString}").toString()
log.info(msg)
def t = new IllegalStateException(msg)
throw t
}
Expand All @@ -112,7 +111,6 @@ class ExplainAction implements SuiteAction {
if (explainString.contains(string)) {
String msg = ("Explain and check failed, expect not contains '${string}',"
+ " but actual explain string is:\n${explainString}").toString()
log.info(msg)
def t = new IllegalStateException(msg)
throw t
}
Expand All @@ -122,7 +120,6 @@ class ExplainAction implements SuiteAction {
if (count != entry.value) {
String msg = ("Explain and check failed, expect multiContains '${string}' , '${entry.value}' times, actural '${count}' times."
+ "Actual explain string is:\n${explainString}").toString()
log.info(msg)
def t = new IllegalStateException(msg)
throw t
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,36 @@ class Suite implements GroovyInterceptable {
return result.values().toList()
}

def check_mv_rewrite_success = { db, mv_sql, query_sql, mv_name ->
def mv_rewrite_success = { query_sql, mv_name ->
explain {
sql(" memo plan ${query_sql}")
contains("${mv_name} chose")
}
}

def mv_rewrite_success_without_check_chosen = { query_sql, mv_name ->
explain {
sql(" memo plan ${query_sql}")
contains("${mv_name} not chose")
}
}

def mv_rewrite_fail = { query_sql, mv_name ->
explain {
sql(" memo plan ${query_sql}")
contains("${mv_name} fail")
}
}

def mv_rewrite_all_fail = {query_sql ->
explain {
sql(" memo plan ${query_sql}")
contains("chose: none")
contains("not chose: none")
}
}

def async_mv_rewrite_success = { db, mv_sql, query_sql, mv_name ->

sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name}"""
sql"""
Expand All @@ -1466,16 +1495,18 @@ class Suite implements GroovyInterceptable {
PROPERTIES ('replication_num' = '1')
AS ${mv_sql}
"""

def job_name = getJobName(db, mv_name);
waitingMTMVTaskFinished(job_name)

sql "analyze table ${mv_name} with sync;"

explain {
sql("${query_sql}")
contains("${mv_name}(${mv_name})")
sql(" memo plan ${query_sql}")
contains("${mv_name} chose")
}
}

def check_mv_rewrite_success_without_check_chosen = { db, mv_sql, query_sql, mv_name ->
def async_mv_rewrite_success_without_check_chosen = { db, mv_sql, query_sql, mv_name ->

sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name}"""
sql"""
Expand All @@ -1488,17 +1519,17 @@ class Suite implements GroovyInterceptable {

def job_name = getJobName(db, mv_name);
waitingMTMVTaskFinished(job_name)

sql "analyze table ${mv_name} with sync;"

explain {
sql("${query_sql}")
check {result ->
def splitResult = result.split("MaterializedViewRewriteFail")
splitResult.length == 2 ? splitResult[0].contains(mv_name) : false
}
sql(" memo plan ${query_sql}")
notContains("${mv_name} fail")
}
}


def check_mv_rewrite_fail = { db, mv_sql, query_sql, mv_name ->
def async_mv_rewrite_fail = { db, mv_sql, query_sql, mv_name ->

sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name}"""
sql"""
Expand All @@ -1511,9 +1542,13 @@ class Suite implements GroovyInterceptable {

def job_name = getJobName(db, mv_name);
waitingMTMVTaskFinished(job_name)

sql "analyze table ${mv_name} with sync;"

explain {
sql("${query_sql}")
notContains("${mv_name}(${mv_name})")
sql(" memo plan ${query_sql}")
notContains("${mv_name} chose")
notContains("${mv_name} not chose")
}
}

Expand Down
Loading