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 @@ -1155,7 +1155,7 @@ public Statistics computeFilter(Filter filter, Statistics inputStats) {
}

private ColumnStatistic getColumnStatistic(TableIf table, String colName, long idxId) {
if (connectContext != null && connectContext.getState().isInternal()) {
if (connectContext != null && connectContext.getState().isPlanWithUnKnownColumnStats()) {
return ColumnStatistic.UNKNOWN;
}
long catalogId;
Expand Down Expand Up @@ -1187,7 +1187,7 @@ private ColumnStatistic getColumnStatistic(TableIf table, String colName, long i

private ColumnStatistic getColumnStatistic(
OlapTableStatistics olapTableStatistics, String colName, List<String> partitionNames) {
if (connectContext != null && connectContext.getState().isInternal()) {
if (connectContext != null && connectContext.getState().isPlanWithUnKnownColumnStats()) {
return ColumnStatistic.UNKNOWN;
}
OlapTable table = olapTableStatistics.olapTable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2493,7 +2493,7 @@ public boolean isEnableHboNonStrictMatchingMode() {
public boolean enableMaterializedViewRewrite = true;

@VariableMgr.VarAttr(name = PRE_MATERIALIZED_VIEW_REWRITE_STRATEGY, needForward = true, fuzzy = true,
description = {"在 RBO 阶段基于结构信息的物化视图透明改写的策略,FORCE_IN_ROB:强制在 RBO 阶段透明改写,"
description = {"在 RBO 阶段基于结构信息的物化视图透明改写的策略,FORCE_IN_RBO:强制在 RBO 阶段透明改写,"
+ "TRY_IN_RBO:如果在 NEED_PRE_REWRITE_RULE_TYPES 中的规则改写成功了,那么就会尝试在 RBO 阶段透明改写"
+ "NOT_IN_RBO:不尝试在 RBO 阶段改写,只在 CBO 阶段改写",
"Whether to enable pre materialized view rewriting based on struct info,"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public class StatisticsCache {

public ColumnStatistic getColumnStatistics(
long catalogId, long dbId, long tblId, long idxId, String colName, ConnectContext ctx) {
if (ctx != null && ctx.getState().isInternal()) {
if (ctx != null && ctx.getState().isPlanWithUnKnownColumnStats()) {
return ColumnStatistic.UNKNOWN;
}
// Need to change base index id to -1 for OlapTable.
Expand Down Expand Up @@ -130,7 +130,7 @@ private ColumnStatistic doGetColumnStatistics(

public PartitionColumnStatistic getPartitionColumnStatistics(long catalogId, long dbId, long tblId, long idxId,
String partName, String colName, ConnectContext ctx) {
if (ctx != null && ctx.getState().isInternal()) {
if (ctx != null && ctx.getState().isPlanWithUnKnownColumnStats()) {
return PartitionColumnStatistic.UNKNOWN;
}
// Need to change base index id to -1 for OlapTable.
Expand Down Expand Up @@ -178,7 +178,7 @@ public Histogram getHistogram(long ctlId, long dbId, long tblId, String colName)

private Optional<Histogram> getHistogram(long ctlId, long dbId, long tblId, long idxId, String colName) {
ConnectContext ctx = ConnectContext.get();
if (ctx != null && ctx.getState().isInternal()) {
if (ctx != null && ctx.getState().isPlanWithUnKnownColumnStats()) {
return Optional.empty();
}
StatisticsCacheKey k = new StatisticsCacheKey(ctlId, dbId, tblId, idxId, colName);
Expand Down Expand Up @@ -398,7 +398,7 @@ public OlapTableStatistics(OlapScan logicalOlapScan) {

// this method can avoid compute table and select index id
public ColumnStatistic getColumnStatistics(String colName, ConnectContext ctx) {
if (ctx != null && ctx.getState().isInternal()) {
if (ctx != null && ctx.getState().isPlanWithUnKnownColumnStats()) {
return ColumnStatistic.UNKNOWN;
}
return doGetColumnStatistics(
Expand All @@ -408,7 +408,7 @@ public ColumnStatistic getColumnStatistics(String colName, ConnectContext ctx) {

public PartitionColumnStatistic getPartitionColumnStatistics(
String partName, String colName, ConnectContext ctx) {
if (ctx != null && ctx.getState().isInternal()) {
if (ctx != null && ctx.getState().isPlanWithUnKnownColumnStats()) {
return PartitionColumnStatistic.UNKNOWN;
}
return doGetPartitionColumnStatistics(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.apache.doris.nereids.util.LogicalPlanBuilder;
import org.apache.doris.nereids.util.MemoTestUtils;
import org.apache.doris.nereids.util.PlanConstructor;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.SessionVariable;
import org.apache.doris.statistics.ColumnStatistic;
import org.apache.doris.statistics.ColumnStatisticBuilder;
Expand Down Expand Up @@ -572,4 +573,39 @@ public long getRowCount(long indexId) {
// because table row count is -1, so disable join reorder
Assertions.assertTrue(cascadesContext.getConnectContext().getSessionVariable().isDisableJoinReorder());
}

@Test
public void testOlapScanWithPlanWithUnknownColumnStats() {
boolean prevFlag = false;
if (ConnectContext.get() != null) {
prevFlag = ConnectContext.get().getState().isPlanWithUnKnownColumnStats();
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(true);
}
try {
long tableId1 = 100;
OlapTable table1 = PlanConstructor.newOlapTable(tableId1, "t_unknown", 0);
List<String> qualifier = ImmutableList.of("test", "t");
SlotReference slot1 = new SlotReference(new ExprId(0), "c1", IntegerType.INSTANCE, true, qualifier,
table1, new Column("c1", PrimitiveType.INT),
table1, new Column("c1", PrimitiveType.INT));

LogicalOlapScan logicalOlapScan1 = (LogicalOlapScan) new LogicalOlapScan(
StatementScopeIdGenerator.newRelationId(), table1,
Collections.emptyList()).withGroupExprLogicalPropChildren(Optional.empty(),
Optional.of(new LogicalProperties(() -> ImmutableList.of(slot1), () -> DataTrait.EMPTY_TRAIT)), ImmutableList.of());

GroupExpression groupExpression = new GroupExpression(logicalOlapScan1, ImmutableList.of());
Group ownerGroup = new Group(null, groupExpression, null);
StatsCalculator.estimate(groupExpression, null);
Statistics stats = ownerGroup.getStatistics();
Assertions.assertEquals(1, stats.columnStatistics().size());
ColumnStatistic colStat = stats.columnStatistics().get(slot1);
Assertions.assertTrue(colStat.isUnKnown);
} finally {
if (ConnectContext.get() != null) {
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(prevFlag);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// 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.statistics;

import org.apache.doris.qe.ConnectContext;
import org.apache.doris.utframe.UtFrameUtils;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class StatisticsCacheTest {

private ConnectContext ctx;

@BeforeEach
public void setUp() throws Exception {
if (ConnectContext.get() == null) {
ctx = UtFrameUtils.createDefaultCtx();
} else {
ctx = ConnectContext.get();
}
}

@Test
public void testGetColumnStatistics_withPlanWithUnknownColumnStats() {
Assumptions.assumeTrue(ConnectContext.get() != null, "ConnectContext not available");

boolean prevFlag = ConnectContext.get().getState().isPlanWithUnKnownColumnStats();
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(true);
try {
StatisticsCache cache = new StatisticsCache();
ColumnStatistic stat = cache.getColumnStatistics(
1L, 1L, 1L, -1L, "col", ConnectContext.get());
Assertions.assertEquals(ColumnStatistic.UNKNOWN, stat,
"Expect UNKNOWN when plan has unknown column stats");
} finally {
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(prevFlag);
}
}

@Test
public void testGetHistogram_withPlanWithUnknownColumnStats() {
Assumptions.assumeTrue(ConnectContext.get() != null, "ConnectContext not available");

boolean prevFlag = ConnectContext.get().getState().isPlanWithUnKnownColumnStats();
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(true);
try {
StatisticsCache cache = new StatisticsCache();
// public getHistogram returns null when underlying optional is empty
Histogram hist = cache.getHistogram(1L, 1L, 1L, "col");
Assertions.assertNull(hist, "Expect null histogram when plan has unknown column stats");
} finally {
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(prevFlag);
}
}

@Test
public void testGetPartitionColumnStatistics_withPlanWithUnknownColumnStats() {
Assumptions.assumeTrue(ConnectContext.get() != null, "ConnectContext not available");

boolean prevFlag = ConnectContext.get().getState().isPlanWithUnKnownColumnStats();
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(true);
try {
StatisticsCache cache = new StatisticsCache();
PartitionColumnStatistic pstat = cache.getPartitionColumnStatistics(
1L, 1L, 1L, -1L, "p", "col", ConnectContext.get());
Assertions.assertEquals(PartitionColumnStatistic.UNKNOWN, pstat,
"Expect UNKNOWN partition col stat when plan has unknown column stats");
} finally {
ConnectContext.get().getState().setPlanWithUnKnownColumnStats(prevFlag);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,10 @@ suite("materialized_view_switch") {
where o_orderdate = '2023-12-10' order by 1, 2, 3, 4, 5;
"""

async_mv_rewrite_success(db, mv_name, query, "mv_name_1")
async_mv_rewrite_success(db, mv_name, query, "mv_name_1", [NOT_IN_RBO])
// because compare total tree, mv fitler can not push down to scan base table in RBO mv rewrite as CBO mv prewrite,
// row count would be bigger than before
async_mv_rewrite_success_without_check_chosen(db, mv_name, query, "mv_name_1", [TRY_IN_RBO, FORCE_IN_RBO])
sql """ DROP MATERIALIZED VIEW IF EXISTS mv_name_1"""

sql "SET enable_materialized_view_rewrite=false"
Expand All @@ -152,7 +155,10 @@ suite("materialized_view_switch") {
sql """ DROP MATERIALIZED VIEW IF EXISTS mv_name_2"""

sql "SET enable_materialized_view_rewrite=true"
async_mv_rewrite_success(db, mv_name, query, "mv_name_3")
async_mv_rewrite_success(db, mv_name, query, "mv_name_3", [NOT_IN_RBO])
// because compare total tree, mv fitler can not push down to scan base table in RBO mv rewrite as CBO mv prewrite,
// row count would be bigger than before
async_mv_rewrite_success_without_check_chosen(db, mv_name, query, "mv_name_3", [TRY_IN_RBO, FORCE_IN_RBO])
sql """ DROP MATERIALIZED VIEW IF EXISTS mv_name_3"""

// test when materialized_view_relation_mapping_max_count is 8
Expand All @@ -167,7 +173,11 @@ suite("materialized_view_switch") {
inner join lineitem t2 on t1.L_ORDERKEY = t2.L_ORDERKEY;
"""
order_qt_query1_0_before "${query1_0}"
async_mv_rewrite_success(db, mv1_0, query1_0, "mv1_0")
async_mv_rewrite_success(db, mv1_0, query1_0, "mv1_0", [NOT_IN_RBO])
// because compare total tree, mv fitler can not push down to scan base table in RBO mv rewrite as CBO mv prewrite,
// row count would be bigger than before
async_mv_rewrite_success_without_check_chosen(db, mv1_0, query1_0, "mv1_0", [TRY_IN_RBO, FORCE_IN_RBO])

order_qt_query1_0_after "${query1_0}"
sql """ DROP MATERIALIZED VIEW IF EXISTS mv1_0"""

Expand Down
Loading