1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-01 06:46:55 +03:00

feat(optimizer): rewrite rule does not descent into a freshly created UNION unit.

This commit is contained in:
drrtuy
2025-06-23 22:17:09 +00:00
parent 464b9a1ca3
commit 3bf4394456
2 changed files with 40 additions and 22 deletions

View File

@ -21,6 +21,8 @@
namespace optimizer { namespace optimizer {
static const std::string RewrittenSubTableAliasPrefix = "$added_sub_";
// Apply a list of rules to a CSEP // Apply a list of rules to a CSEP
bool optimizeCSEPWithRules(execplan::CalpontSelectExecutionPlan& root, const std::vector<Rule>& rules) { bool optimizeCSEPWithRules(execplan::CalpontSelectExecutionPlan& root, const std::vector<Rule>& rules) {
@ -47,9 +49,9 @@ bool Rule::apply(execplan::CalpontSelectExecutionPlan& root) const
{ {
bool changedThisRound = false; bool changedThisRound = false;
bool hasBeenApplied = false; bool hasBeenApplied = false;
do do
{ {
changedThisRound = walk(root); changedThisRound = walk(root) && !applyOnlyOnce;
hasBeenApplied = changedThisRound; hasBeenApplied = changedThisRound;
} while (changedThisRound); } while (changedThisRound);
@ -70,7 +72,7 @@ bool Rule::walk(execplan::CalpontSelectExecutionPlan& csep) const
} }
auto& csepLocal = *csepPtr; auto& csepLocal = *csepPtr;
rewrite |= apply(csepLocal); rewrite |= walk(csepLocal);
} }
for (auto& unionUnit : csep.unionVec()) for (auto& unionUnit : csep.unionVec())
@ -82,7 +84,7 @@ bool Rule::walk(execplan::CalpontSelectExecutionPlan& csep) const
} }
auto& unionUnitLocal = *unionUnitPtr; auto& unionUnitLocal = *unionUnitPtr;
rewrite |= apply(unionUnitLocal); rewrite |= walk(unionUnitLocal);
} }
if (matchRule(csep)) if (matchRule(csep))
@ -112,7 +114,7 @@ bool matchParallelCES(execplan::CalpontSelectExecutionPlan& csep)
auto tables = csep.tableList(); auto tables = csep.tableList();
// This is leaf and there are no other tables at this level in neither UNION, nor derived table. // This is leaf and there are no other tables at this level in neither UNION, nor derived table.
// WIP filter out CSEPs with orderBy, groupBy, having // WIP filter out CSEPs with orderBy, groupBy, having
// WIP filter out CSEPs with nonSimpleColumns in projection // Filter out tables that were re-written.
return tables.size() == 1 && !tables[0].isColumnstore() && !tableIsInUnion(tables[0], csep); return tables.size() == 1 && !tables[0].isColumnstore() && !tableIsInUnion(tables[0], csep);
} }
@ -134,7 +136,7 @@ void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep)
auto tables = csep.tableList(); auto tables = csep.tableList();
execplan::CalpontSelectExecutionPlan::TableList newTableList; execplan::CalpontSelectExecutionPlan::TableList newTableList;
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList; execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
static const std::string aliasPrefix = "$sub_"; execplan::CalpontSelectExecutionPlan::ReturnedColumnList newReturnedColumns;
// ATM Must be only 1 table // ATM Must be only 1 table
for (auto& table: tables) for (auto& table: tables)
@ -143,32 +145,35 @@ void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep)
{ {
auto derivedSCEP = csep.cloneWORecursiveSelects(); auto derivedSCEP = csep.cloneWORecursiveSelects();
// need to add a level here // need to add a level here
std::string alias = aliasPrefix + table.schema + "_" + table.table; std::string tableAlias = RewrittenSubTableAliasPrefix + table.schema + "_" + table.table;
derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM); derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM);
derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS); derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS);
derivedSCEP->derivedTbAlias(alias); derivedSCEP->derivedTbAlias(tableAlias);
// TODO: hardcoded for now // TODO: hardcoded for now
size_t parallelFactor = 2; size_t parallelFactor = 2;
auto additionalUnionVec = makeUnionFromTable(parallelFactor, csep); auto additionalUnionVec = makeUnionFromTable(parallelFactor, csep);
derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(), additionalUnionVec.end()); derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(), additionalUnionVec.end());
size_t colPosition = 0;
// change parent to derived table columns // change parent to derived table columns
for (auto& rc : csep.returnedCols()) for (auto& rc : csep.returnedCols())
{ {
auto* sc = dynamic_cast<execplan::SimpleColumn*>(rc.get()); auto rc_ = boost::make_shared<execplan::SimpleColumn>(*rc);
if (sc) // TODO timezone and result type are not copied
{ // TODO add specific ctor for this functionality
sc->tableName(""); rc_->tableName("");
sc->schemaName(""); rc_->schemaName("");
sc->tableAlias(alias); rc_->tableAlias(tableAlias);
sc->colPosition(0); rc_->colPosition(colPosition++);
} rc_->resultType(rc->resultType());
newReturnedColumns.push_back(rc_);
} }
newDerivedTableList.push_back(derivedSCEP); newDerivedTableList.push_back(derivedSCEP);
execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", alias, ""); execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, "");
newTableList.push_back(tn); newTableList.push_back(tn);
} }
} }
@ -177,6 +182,8 @@ void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep)
csep.derivedTableList(newDerivedTableList); csep.derivedTableList(newDerivedTableList);
// Replace table list with new table list populated with union units // Replace table list with new table list populated with union units
csep.tableList(newTableList); csep.tableList(newTableList);
} csep.returnedCols(newReturnedColumns);
}
} }

View File

@ -24,13 +24,24 @@ namespace optimizer {
struct Rule struct Rule
{ {
Rule(std::string&& name, bool (*matchRule)(execplan::CalpontSelectExecutionPlan&), using RuleMatcher = bool (*)(execplan::CalpontSelectExecutionPlan&);
void (*applyRule)(execplan::CalpontSelectExecutionPlan&)) using RuleApplier = void (*)(execplan::CalpontSelectExecutionPlan&);
Rule(std::string&& name, RuleMatcher matchRule, RuleApplier applyRule)
: name(name), matchRule(matchRule), applyRule(applyRule) {}; : name(name), matchRule(matchRule), applyRule(applyRule) {};
std::string name; std::string name;
bool (*matchRule)(execplan::CalpontSelectExecutionPlan&); RuleMatcher matchRule;
void (*applyRule)(execplan::CalpontSelectExecutionPlan&); RuleApplier applyRule;
// TODO Wrap CSEP into Nodes to be able to navigate up and down the tree and remove this flag
bool applyOnlyOnce = true;
Rule() = default;
Rule(const Rule&) = default;
Rule(Rule&&) = default;
Rule& operator=(const Rule&) = default;
Rule& operator=(Rule&&) = default;
bool apply(execplan::CalpontSelectExecutionPlan& csep) const; bool apply(execplan::CalpontSelectExecutionPlan& csep) const;
bool walk(execplan::CalpontSelectExecutionPlan& csep) const; bool walk(execplan::CalpontSelectExecutionPlan& csep) const;
}; };