1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

feat(optimizer): first cut for rewrite foreign table into UNION rule

This commit is contained in:
drrtuy
2025-06-09 18:51:52 +00:00
parent 79008f4f69
commit e73e5834ab
3 changed files with 200 additions and 20 deletions

View File

@ -205,7 +205,7 @@ string CalpontSelectExecutionPlan::toString(const size_t ident) const
{ {
ostringstream output; ostringstream output;
output << std::string(ident, ' ') << "SELECT "; output << "SELECT ";
if (distinct()) if (distinct())
{ {
@ -340,14 +340,16 @@ string CalpontSelectExecutionPlan::toString(const size_t ident) const
output << "QueryType: " << queryType() << endlWithIndent(ident); output << "QueryType: " << queryType() << endlWithIndent(ident);
if (!unionVec().empty()) if (!unionVec().empty())
output << "\n--- Union Unit ---" << endlWithIndent(ident); {
output << "--- Union Unit ---";
}
for (unsigned i = 0; i < unionVec().size(); i++) for (unsigned i = 0; i < unionVec().size(); i++)
{ {
CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(unionVec()[i].get()); CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(unionVec()[i].get());
if (plan) if (plan)
output << "{" << *plan << "}\n" << endlWithIndent(ident); output << endlWithIndent(ident) << "{" << plan->toString(ident + 2) << "}\n" << endlWithIndent(ident);
} }
return output.str(); return output.str();
@ -858,4 +860,151 @@ void CalpontSelectExecutionPlan::pron(std::string&& pron)
fPron = pron; fPron = pron;
} }
execplan::SCSEP CalpontSelectExecutionPlan::cloneWORecursiveSelects()
{
execplan::SCSEP newPlan(new CalpontSelectExecutionPlan(fLocation));
// Copy simple members
newPlan->fLocalQuery = fLocalQuery;
newPlan->fTableAlias = fTableAlias;
newPlan->fLocation = fLocation;
newPlan->fDependent = fDependent;
newPlan->fData = fData;
newPlan->fSessionID = fSessionID;
newPlan->fTxnID = fTxnID;
newPlan->fVerID = fVerID;
newPlan->fSchemaName = fSchemaName;
newPlan->fTableName = fTableName;
newPlan->fTraceFlags = fTraceFlags;
newPlan->fStatementID = fStatementID;
newPlan->fDistinct = fDistinct;
newPlan->fOverrideLargeSideEstimate = fOverrideLargeSideEstimate;
newPlan->fDistinctUnionNum = fDistinctUnionNum;
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;
newPlan->fStringTableThreshold = fStringTableThreshold;
newPlan->fSpecHandlerProcessed = fSpecHandlerProcessed;
newPlan->fOrderByThreads = fOrderByThreads;
newPlan->fUuid = fUuid;
newPlan->fDJSSmallSideLimit = fDJSSmallSideLimit;
newPlan->fDJSLargeSideLimit = fDJSLargeSideLimit;
newPlan->fDJSPartitionSize = fDJSPartitionSize;
newPlan->fDJSMaxPartitionTreeDepth = fDJSMaxPartitionTreeDepth;
newPlan->fDJSForceRun = fDJSForceRun;
newPlan->fMaxPmJoinResultCount = fMaxPmJoinResultCount;
newPlan->fUMMemLimit = fUMMemLimit;
newPlan->fIsDML = fIsDML;
newPlan->fTimeZone = fTimeZone;
newPlan->fPron = fPron;
newPlan->fWithRollup = fWithRollup;
// Deep copy of ReturnedColumnList
ReturnedColumnList newReturnedCols;
for (const auto& col : fReturnedCols)
{
if (col)
newReturnedCols.push_back(SRCP(col->clone()));
}
newPlan->returnedCols(newReturnedCols);
// Deep copy of filters
if (fFilters)
newPlan->filters(new ParseTree(*fFilters));
// Deep copy of filter token list
newPlan->filterTokenList(fFilterTokenList);
newPlan->havingTokenList(fHavingTokenList);
// Deep copy of subselects
// SelectList newSubSelects;
// for (const auto& sel : fSubSelects)
// {
// if (sel)
// newSubSelects.push_back(SCEP(sel->clone()));
// }
// newPlan->subSelects(newSubSelects);
// Deep copy of group by columns
GroupByColumnList newGroupByCols;
for (const auto& col : fGroupByCols)
{
if (col)
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)
{
if (col)
newOrderByCols.push_back(SRCP(col->clone()));
}
newPlan->orderByCols(newOrderByCols);
// Deep copy of column map
ColumnMap newColumnMap;
for (const auto& entry : fColumnMap)
{
if (entry.second)
newColumnMap.insert(ColumnMap::value_type(entry.first, SRCP(entry.second->clone())));
}
newPlan->columnMap(newColumnMap);
// Copy RM parameters
newPlan->rmParms(frmParms);
// Deep copy of table list
newPlan->tableList(fTableList);
// // Deep copy of derived table list
// SelectList newDerivedTableList;
// for (const auto& sel : fDerivedTableList)
// {
// if (sel)
// newDerivedTableList.push_back(SCEP(sel->clone()));
// }
// newPlan->derivedTableList(newDerivedTableList);
// // Deep copy of union vector
// SelectList newUnionVec;
// for (const auto& sel : fUnionVec)
// {
// if (sel)
// newUnionVec.push_back(SCEP(sel->clone()));
// }
// newPlan->unionVec(newUnionVec);
// // Deep copy of select subqueries
// SelectList newSelectSubList;
// for (const auto& sel : fSelectSubList)
// {
// if (sel)
// newSelectSubList.push_back(SCEP(sel->clone()));
// }
// newPlan->selectSubList(newSelectSubList);
// // Deep copy of subquery list
// std::vector<SCSEP> newSubSelectList;
// for (const auto& sel : fSubSelectList)
// {
// if (sel)
// newSubSelectList.push_back(SCSEP(sel->clone()));
// }
// newPlan->subSelectList(newSubSelectList);
return newPlan;
}
} // namespace execplan } // namespace execplan

View File

@ -159,6 +159,7 @@ class CalpontSelectExecutionPlan : public CalpontExecutionPlan
*/ */
~CalpontSelectExecutionPlan() override; ~CalpontSelectExecutionPlan() override;
execplan::SCSEP cloneWORecursiveSelects();
/** /**
* Access and mutator methods * Access and mutator methods
*/ */

View File

@ -9206,14 +9206,26 @@ int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* /*thd*/, S
return 0; return 0;
} }
bool tableIsInUnion(const execplan::CalpontSystemCatalog::TableAliasName& table, CalpontSelectExecutionPlan& csep)
{
return std::any_of(csep.unionVec().begin(), csep.unionVec().end(),
[&table](const auto& unionUnit) {
auto unionUnitLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(unionUnit.get());
bool tableIsPresented = std::any_of(unionUnitLocal.tableList().begin(), unionUnitLocal.tableList().end(),
[&table](const auto& unionTable) {
return unionTable == table;
});
return tableIsPresented;
});
}
bool matchParallelCES(CalpontSelectExecutionPlan& csep) bool matchParallelCES(CalpontSelectExecutionPlan& csep)
{ {
std::cout << csep.toString() << std::endl;
auto tables = csep.tableList(); auto tables = csep.tableList();
// This is leaf and there are no other tables at this level. // This is leaf and there are no other tables at this level.
for (auto& table : tables) for (auto& table : tables)
{ {
if (!table.isColumnstore()) if (!table.isColumnstore() && !tableIsInUnion(table, csep))
{ {
return true; return true;
} }
@ -9222,28 +9234,37 @@ bool matchParallelCES(CalpontSelectExecutionPlan& csep)
return false; return false;
} }
// CalpontSelectExecutionPlan tableIntoUnion(CalpontSelectExecutionPlan& table, CalpontSelectExecutionPlan& csep) CalpontSelectExecutionPlan::SelectList makeUnionFromTable(const size_t numberOfLegs,
// { CalpontSelectExecutionPlan& csep)
// auto* unionCSEP = {new CalpontSelectExecutionPlan()}; {
// CalpontSelectExecutionPlan::ReturnedColumnList returnedColumnList; CalpontSelectExecutionPlan::SelectList unionVec;
// CalpontSelectExecutionPlan::ColumnMap colMap; unionVec.reserve(numberOfLegs);
for (size_t i = 0; i < numberOfLegs; ++i)
{
unionVec.emplace_back(csep.cloneWORecursiveSelects());
}
// unionSCEP.unionVec({csep}); return unionVec;
// return unionSCEP; }
// }
void applyParallelCES(CalpontSelectExecutionPlan& csep) void applyParallelCES(CalpontSelectExecutionPlan& csep)
{ {
std::cout << "applyParallelCES" << std::endl;
std::cout << "original unionVec size " << csep.unionVec().size() << std::endl;
auto tables = csep.tableList(); auto tables = csep.tableList();
for (auto it = tables.begin(); it != tables.end(); ++it) for (auto it = tables.begin(); it != tables.end(); ++it)
{ {
if (!it->isColumnstore()) if (!it->isColumnstore())
{ {
// auto unionSCEP = tableIntoUnion(*it, csep); size_t parallelFactor = 2;
// tables.erase(it); auto additionalUnionVec = makeUnionFromTable(parallelFactor, csep);
// csep.unionVec().push_back(unionSCEP); csep.unionVec().insert(csep.unionVec().end(), additionalUnionVec.begin(), additionalUnionVec.end());
} }
} }
std::cout << "modified CSEP" << std::endl;
std::cout << "unionVec size " << csep.unionVec().size() << std::endl;
} }
struct Rule struct Rule
@ -9257,13 +9278,18 @@ struct Rule
void (*apply)(CalpontSelectExecutionPlan&); void (*apply)(CalpontSelectExecutionPlan&);
bool walk(CalpontSelectExecutionPlan& csep) bool walk(CalpontSelectExecutionPlan& csep)
{ {
bool rewrite = false;
for (auto& table : csep.derivedTableList()) for (auto& table : csep.derivedTableList())
{ {
auto csepLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(table.get()); auto csepLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(table.get());
if (match(csepLocal)) if (match(csepLocal))
{ {
apply(csepLocal); apply(csepLocal);
return true; rewrite = true;
}
else
{
rewrite |= walk(csepLocal);
} }
} }
@ -9274,17 +9300,21 @@ struct Rule
if (match(unionUnitLocal)) if (match(unionUnitLocal))
{ {
apply(unionUnitLocal); apply(unionUnitLocal);
return true; rewrite = true;
}
else
{
rewrite |= walk(unionUnitLocal);
} }
} }
if (match(csep)) if (match(csep))
{ {
apply(csep); apply(csep);
return true; rewrite = true;
} }
return false; return rewrite;
} }
}; };