You've already forked mariadb-columnstore-engine
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:
@@ -967,8 +967,9 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneWORecursiveSelects()
|
|||||||
return newPlan;
|
return newPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
|
// This clone must return CSEP w/o sub-selects, group by, order by, having limit.
|
||||||
const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias)
|
execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelectsGbObHaving(
|
||||||
|
const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias, const bool withFilters)
|
||||||
{
|
{
|
||||||
execplan::SCSEP newPlan(new CalpontSelectExecutionPlan(fLocation));
|
execplan::SCSEP newPlan(new CalpontSelectExecutionPlan(fLocation));
|
||||||
|
|
||||||
@@ -991,9 +992,6 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
|
|||||||
newPlan->fSubType = fSubType;
|
newPlan->fSubType = fSubType;
|
||||||
newPlan->fDerivedTbAlias = fDerivedTbAlias;
|
newPlan->fDerivedTbAlias = fDerivedTbAlias;
|
||||||
newPlan->fDerivedTbView = fDerivedTbView;
|
newPlan->fDerivedTbView = fDerivedTbView;
|
||||||
newPlan->fLimitStart = fLimitStart;
|
|
||||||
newPlan->fLimitNum = fLimitNum;
|
|
||||||
newPlan->fHasOrderBy = fHasOrderBy;
|
|
||||||
newPlan->fStringScanThreshold = fStringScanThreshold;
|
newPlan->fStringScanThreshold = fStringScanThreshold;
|
||||||
newPlan->fQueryType = fQueryType;
|
newPlan->fQueryType = fQueryType;
|
||||||
newPlan->fPriority = fPriority;
|
newPlan->fPriority = fPriority;
|
||||||
@@ -1037,34 +1035,13 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
|
|||||||
// Deep copy of filters
|
// Deep copy of filters
|
||||||
// WIP only filters that apply to the target table must be left intact
|
// WIP only filters that apply to the target table must be left intact
|
||||||
// replace all irrelevant branches with true
|
// replace all irrelevant branches with true
|
||||||
if (fFilters)
|
if (fFilters && withFilters)
|
||||||
{
|
{
|
||||||
newPlan->filters(new ParseTree(*fFilters));
|
newPlan->filters(new ParseTree(*fFilters));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deep copy of filter token list
|
// Deep copy of filter token list
|
||||||
newPlan->filterTokenList(fFilterTokenList);
|
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
|
// Deep copy of column map
|
||||||
ColumnMap newColumnMap;
|
ColumnMap newColumnMap;
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ class CalpontSelectExecutionPlan : public CalpontExecutionPlan
|
|||||||
*/
|
*/
|
||||||
execplan::SCSEP cloneWORecursiveSelects();
|
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
|
* Access and mutator methods
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ void derivedTableOptimization(gp_walk_info* gwip, SCSEP& csep)
|
|||||||
|
|
||||||
for (int64_t i = cols.size() - 1; i >= 0; i--)
|
for (int64_t i = cols.size() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
// if (cols[i]->derivedTable().empty())
|
|
||||||
if (cols[i]->refCount() == 0)
|
if (cols[i]->refCount() == 0)
|
||||||
{
|
{
|
||||||
if (cols[i]->derivedRefCol())
|
if (cols[i]->derivedRefCol())
|
||||||
|
|||||||
@@ -248,69 +248,102 @@ std::optional<FilterRangeBounds<T>> populateRangeBounds(Histogram_json_hb* colum
|
|||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO char and other numerical types support
|
// TODO char and other numerical types support
|
||||||
execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(
|
execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(
|
||||||
execplan::CalpontSelectExecutionPlan& csep, execplan::CalpontSystemCatalog::TableAliasName& table,
|
execplan::CalpontSelectExecutionPlan& csep, execplan::CalpontSystemCatalog::TableAliasName& table,
|
||||||
optimizer::RBOptimizerContext& ctx)
|
optimizer::RBOptimizerContext& ctx)
|
||||||
{
|
{
|
||||||
execplan::CalpontSelectExecutionPlan::SelectList unionVec;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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;
|
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();
|
auto tables = csep.tableList();
|
||||||
execplan::CalpontSelectExecutionPlan::TableList newTableList;
|
execplan::CalpontSelectExecutionPlan::TableList newTableList;
|
||||||
// TODO support CSEPs with derived tables
|
// TODO support CSEPs with derived tables
|
||||||
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
||||||
cal_impl_if::TableAliasMap tableAliasMap;
|
optimizer::TableAliasMap tableAliasMap;
|
||||||
bool ruleHasBeenApplied = false;
|
bool ruleHasBeenApplied = false;
|
||||||
|
|
||||||
for (auto& table : tables)
|
for (auto& table : tables)
|
||||||
@@ -323,37 +356,14 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
|
|||||||
// TODO add column statistics check to the corresponding match
|
// TODO add column statistics check to the corresponding match
|
||||||
if (!table.isColumnstore() && anyColumnStatistics)
|
if (!table.isColumnstore() && anyColumnStatistics)
|
||||||
{
|
{
|
||||||
// Don't copy filters for this
|
std::string tableAlias = optimizer::RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" +
|
||||||
auto derivedSCEP = csep.cloneForTableWORecursiveSelects(table);
|
std::to_string(ctx.uniqueId);
|
||||||
// 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
|
|
||||||
tableAliasMap.insert({table, {tableAlias, 0}});
|
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, "");
|
execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, "");
|
||||||
newTableList.push_back(tn);
|
newTableList.push_back(tn);
|
||||||
|
|
||||||
|
auto derivedSCEP = createDerivedTableFromTable(csep, table, tableAlias, ctx);
|
||||||
|
newDerivedTableList.push_back(std::move(derivedSCEP));
|
||||||
ruleHasBeenApplied = true;
|
ruleHasBeenApplied = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user