1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-10-31 18:30:33 +03:00

chore(rbo,rules,QA): clone now does not copy OB, GB, HAVING and optionally filters.

This commit is contained in:
drrtuy
2025-08-05 16:00:16 +00:00
parent c19c49ba13
commit 6c75faee88
4 changed files with 96 additions and 109 deletions

View File

@@ -967,8 +967,9 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneWORecursiveSelects()
return newPlan;
}
execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias)
// This clone must return CSEP w/o sub-selects, group by, order by, having limit.
execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelectsGbObHaving(
const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias, const bool withFilters)
{
execplan::SCSEP newPlan(new CalpontSelectExecutionPlan(fLocation));
@@ -991,9 +992,6 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
newPlan->fSubType = fSubType;
newPlan->fDerivedTbAlias = fDerivedTbAlias;
newPlan->fDerivedTbView = fDerivedTbView;
newPlan->fLimitStart = fLimitStart;
newPlan->fLimitNum = fLimitNum;
newPlan->fHasOrderBy = fHasOrderBy;
newPlan->fStringScanThreshold = fStringScanThreshold;
newPlan->fQueryType = fQueryType;
newPlan->fPriority = fPriority;
@@ -1037,34 +1035,13 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
// Deep copy of filters
// WIP only filters that apply to the target table must be left intact
// replace all irrelevant branches with true
if (fFilters)
if (fFilters && withFilters)
{
newPlan->filters(new ParseTree(*fFilters));
}
// Deep copy of filter token list
newPlan->filterTokenList(fFilterTokenList);
newPlan->havingTokenList(fHavingTokenList);
// Deep copy of group by columns
GroupByColumnList newGroupByCols;
for (const auto& col : fGroupByCols)
{
newGroupByCols.push_back(SRCP(col->clone()));
}
newPlan->groupByCols(newGroupByCols);
// Deep copy of having clause
if (fHaving)
newPlan->having(new ParseTree(*fHaving));
// Deep copy of order by columns
OrderByColumnList newOrderByCols;
for (const auto& col : fOrderByCols)
{
newOrderByCols.push_back(SRCP(col->clone()));
}
newPlan->orderByCols(newOrderByCols);
// Deep copy of column map
ColumnMap newColumnMap;

View File

@@ -164,7 +164,8 @@ class CalpontSelectExecutionPlan : public CalpontExecutionPlan
*/
execplan::SCSEP cloneWORecursiveSelects();
execplan::SCSEP cloneForTableWORecursiveSelects(const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias);
execplan::SCSEP cloneForTableWORecursiveSelectsGbObHaving(
const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias, const bool withFilters = true);
/**
* Access and mutator methods

View File

@@ -101,7 +101,6 @@ void derivedTableOptimization(gp_walk_info* gwip, SCSEP& csep)
for (int64_t i = cols.size() - 1; i >= 0; i--)
{
// if (cols[i]->derivedTable().empty())
if (cols[i]->refCount() == 0)
{
if (cols[i]->derivedRefCol())

View File

@@ -248,69 +248,102 @@ std::optional<FilterRangeBounds<T>> populateRangeBounds(Histogram_json_hb* colum
return bounds;
}
// TODO char and other numerical types support
execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(
execplan::CalpontSelectExecutionPlan& csep, execplan::CalpontSystemCatalog::TableAliasName& table,
optimizer::RBOptimizerContext& ctx)
execplan::CalpontSelectExecutionPlan& csep, execplan::CalpontSystemCatalog::TableAliasName& table,
optimizer::RBOptimizerContext& ctx)
{
execplan::CalpontSelectExecutionPlan::SelectList unionVec;
// SC type controls an integral type used to produce suitable filters. The continuation of this function
// should become a template function based on SC type.
auto keyColumnAndStatistics = chooseKeyColumnAndStatistics(table, ctx);
if (!keyColumnAndStatistics)
{
return unionVec;
}
auto& [keyColumn, columnStatistics] = keyColumnAndStatistics.value();
std::cout << "makeUnionFromTable keyColumn " << keyColumn.toString() << std::endl;
std::cout << "makeUnionFromTable RC front " << csep.returnedCols().front()->toString() << std::endl;
// TODO char and other numerical types support
auto boundsOpt = populateRangeBounds<uint64_t>(columnStatistics);
if (!boundsOpt.has_value())
{
return unionVec;
}
auto& bounds = boundsOpt.value();
// These bounds produce low <= col < high
if (bounds.size() > 1)
{
for (size_t i = 0; i <= bounds.size() - 2; ++i)
{
auto clonedCSEP = csep.cloneForTableWORecursiveSelects(table);
// Add BETWEEN based on key column range
auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds[i], false);
clonedCSEP->filters(filter);
// To create CES filter we need to have a column in the column map
clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())});
unionVec.push_back(clonedCSEP);
}
}
// This last bound produces low <= col <= high
// TODO add NULLs into filter of the last step
if (!bounds.empty())
{
auto clonedCSEP = csep.cloneForTableWORecursiveSelects(table);
auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds.back(), true);
clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())});
clonedCSEP->filters(filter);
unionVec.push_back(clonedCSEP);
}
execplan::CalpontSelectExecutionPlan::SelectList unionVec;
// SC type controls an integral type used to produce suitable filters. The continuation of this function
// should become a template function based on SC type.
auto keyColumnAndStatistics = chooseKeyColumnAndStatistics(table, ctx);
if (!keyColumnAndStatistics)
{
return unionVec;
}
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx)
auto& [keyColumn, columnStatistics] = keyColumnAndStatistics.value();
std::cout << "makeUnionFromTable keyColumn " << keyColumn.toString() << std::endl;
std::cout << "makeUnionFromTable RC front " << csep.returnedCols().front()->toString() << std::endl;
// TODO char and other numerical types support
auto boundsOpt = populateRangeBounds<uint64_t>(columnStatistics);
if (!boundsOpt.has_value())
{
return unionVec;
}
auto& bounds = boundsOpt.value();
// These bounds produce low <= col < high
if (bounds.size() > 1)
{
for (size_t i = 0; i <= bounds.size() - 2; ++i)
{
auto clonedCSEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table);
// Add BETWEEN based on key column range
auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds[i], false);
clonedCSEP->filters(filter);
// To create CES filter we need to have a column in the column map
clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())});
unionVec.push_back(clonedCSEP);
}
}
// This last bound produces low <= col <= high
// TODO add NULLs into filter of the last step
if (!bounds.empty())
{
auto clonedCSEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table);
auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds.back(), true);
clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())});
clonedCSEP->filters(filter);
unionVec.push_back(clonedCSEP);
}
return unionVec;
}
execplan::SCSEP createDerivedTableFromTable(
execplan::CalpontSelectExecutionPlan& csep,
const execplan::CalpontSystemCatalog::TableAliasName& table,
const std::string& tableAlias,
optimizer::RBOptimizerContext& ctx)
{
// Don't copy filters for this
auto derivedSCEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table, false);
// Remove the filters as they were pushed down to union units
// This is inappropriate for EXISTS filter and join conditions
// WIP replace with filters applied to filters, so that only relevant filters are left
// WIP Ugly hack to avoid leaks
auto* derivedCSEP = dynamic_cast<execplan::CalpontSelectExecutionPlan*>(derivedSCEP.get());
// TODO more rigorous error handling.
if (!derivedCSEP)
{
return execplan::SCSEP();
}
auto additionalUnionVec = makeUnionFromTable(*derivedCSEP, const_cast<execplan::CalpontSystemCatalog::TableAliasName&>(table), ctx);
// TODO add original alias to support multiple same name tables
derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM);
derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS);
derivedSCEP->derivedTbAlias(tableAlias);
derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(),
additionalUnionVec.end());
return derivedSCEP;
}
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx)
{
auto tables = csep.tableList();
execplan::CalpontSelectExecutionPlan::TableList newTableList;
// TODO support CSEPs with derived tables
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
cal_impl_if::TableAliasMap tableAliasMap;
optimizer::TableAliasMap tableAliasMap;
bool ruleHasBeenApplied = false;
for (auto& table : tables)
@@ -323,37 +356,14 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
// TODO add column statistics check to the corresponding match
if (!table.isColumnstore() && anyColumnStatistics)
{
// Don't copy filters for this
auto derivedSCEP = csep.cloneForTableWORecursiveSelects(table);
// Remove the filters as they were pushed down to union units
// This is inappropriate for EXISTS filter and join conditions
// WIP replace with filters applied to filters, so that only relevant filters are left
// WIP Ugly hack to avoid leaks
auto unusedFilters = derivedSCEP->filters();
delete unusedFilters;
derivedSCEP->filters(nullptr);
auto* derivedCSEP = dynamic_cast<execplan::CalpontSelectExecutionPlan*>(derivedSCEP.get());
if (!derivedCSEP)
{
continue;
}
auto additionalUnionVec = makeUnionFromTable(*derivedCSEP, table, ctx);
// need to add a level here
std::string tableAlias = RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" +
std::to_string(ctx.uniqueId);
// TODO add original alias to support multiple same name tables
std::string tableAlias = optimizer::RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" +
std::to_string(ctx.uniqueId);
tableAliasMap.insert({table, {tableAlias, 0}});
derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM);
derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS);
derivedSCEP->derivedTbAlias(tableAlias);
derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(),
additionalUnionVec.end());
newDerivedTableList.push_back(derivedSCEP);
execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, "");
newTableList.push_back(tn);
auto derivedSCEP = createDerivedTableFromTable(csep, table, tableAlias, ctx);
newDerivedTableList.push_back(std::move(derivedSCEP));
ruleHasBeenApplied = true;
}
else