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
feat(rbo,rules,QA): SC in upper layer filters are updated.
This commit is contained in:
@@ -612,7 +612,6 @@ inline ParseTree& ParseTree::operator=(const ParseTree& rhs)
|
|||||||
{
|
{
|
||||||
if (this != &rhs)
|
if (this != &rhs)
|
||||||
{
|
{
|
||||||
// copyTree(*this, rhs);
|
|
||||||
copyTree(rhs);
|
copyTree(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7596,8 +7596,11 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP&
|
|||||||
// Derived table projection list optimization.
|
// Derived table projection list optimization.
|
||||||
derivedTableOptimization(&gwi, csep);
|
derivedTableOptimization(&gwi, csep);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
optimizer::RBOptimizerContext ctx(gwi, *thd, csep->traceOn());
|
optimizer::RBOptimizerContext ctx(gwi, *thd, csep->traceOn());
|
||||||
|
// TODO RBO can crash or fail leaving CSEP in an invalid state, so there must be a valid CSEP copy
|
||||||
|
// TBD There is a tradeoff b/w copy per rule and copy per optimizer run.
|
||||||
bool csepWasOptimized = optimizer::optimizeCSEP(*csep, ctx);
|
bool csepWasOptimized = optimizer::optimizeCSEP(*csep, ctx);
|
||||||
if (csep->traceOn() && csepWasOptimized)
|
if (csep->traceOn() && csepWasOptimized)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -345,6 +345,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
||||||
optimizer::TableAliasMap tableAliasMap;
|
optimizer::TableAliasMap tableAliasMap;
|
||||||
bool ruleHasBeenApplied = false;
|
bool ruleHasBeenApplied = false;
|
||||||
|
optimizer::TableAliasToNewAliasAndSCPositionsMap tableAliasToSCPositionsMap;
|
||||||
|
|
||||||
for (auto& table : tables)
|
for (auto& table : tables)
|
||||||
{
|
{
|
||||||
@@ -359,6 +360,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
std::string tableAlias = optimizer::RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" +
|
std::string tableAlias = optimizer::RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" +
|
||||||
std::to_string(ctx.uniqueId);
|
std::to_string(ctx.uniqueId);
|
||||||
tableAliasMap.insert({table, {tableAlias, 0}});
|
tableAliasMap.insert({table, {tableAlias, 0}});
|
||||||
|
tableAliasToSCPositionsMap.insert({table, {tableAlias, {}, 0}});
|
||||||
execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, "");
|
execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, "");
|
||||||
newTableList.push_back(tn);
|
newTableList.push_back(tn);
|
||||||
|
|
||||||
@@ -386,6 +388,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
std::cout << "RC table schema " << sameTableAliasOpt->schema << " table " << sameTableAliasOpt->table
|
std::cout << "RC table schema " << sameTableAliasOpt->schema << " table " << sameTableAliasOpt->table
|
||||||
<< " alias " << sameTableAliasOpt->alias << std::endl;
|
<< " alias " << sameTableAliasOpt->alias << std::endl;
|
||||||
auto tableAliasIt = tableAliasMap.find(*sameTableAliasOpt);
|
auto tableAliasIt = tableAliasMap.find(*sameTableAliasOpt);
|
||||||
|
auto tableAliasToSCPositionsIt = tableAliasToSCPositionsMap.find(*sameTableAliasOpt);
|
||||||
if (tableAliasIt != tableAliasMap.end())
|
if (tableAliasIt != tableAliasMap.end())
|
||||||
{
|
{
|
||||||
std::cout << "Replacing RC with new SC" << std::endl;
|
std::cout << "Replacing RC with new SC" << std::endl;
|
||||||
@@ -395,8 +398,30 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
newSC->tableName("");
|
newSC->tableName("");
|
||||||
newSC->schemaName("");
|
newSC->schemaName("");
|
||||||
newSC->tableAlias(newTableAlias);
|
newSC->tableAlias(newTableAlias);
|
||||||
newSC->colPosition(colPosition++);
|
|
||||||
newSC->alias(rc->alias());
|
newSC->alias(rc->alias());
|
||||||
|
|
||||||
|
auto* sc = dynamic_cast<execplan::SimpleColumn*>(rc.get());
|
||||||
|
if (sc)
|
||||||
|
{
|
||||||
|
auto& [unused, SCAliasToPosCounterMap, currentColPosition] = tableAliasToSCPositionsIt->second;
|
||||||
|
auto it = SCAliasToPosCounterMap.find(sc->columnName());
|
||||||
|
if (it == SCAliasToPosCounterMap.end())
|
||||||
|
{
|
||||||
|
SCAliasToPosCounterMap.insert({sc->columnName(), currentColPosition++});
|
||||||
|
std::cout << " first case new column in the map colPosition " << SCAliasToPosCounterMap[sc->columnName()] << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " first case reusing column from the map colPosition " << SCAliasToPosCounterMap[sc->columnName()] << std::endl;
|
||||||
|
}
|
||||||
|
assert(SCAliasToPosCounterMap[sc->columnName()] == colPosition);
|
||||||
|
newSC->colPosition(SCAliasToPosCounterMap[sc->columnName()]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newSC->colPosition(colPosition++);
|
||||||
|
}
|
||||||
|
|
||||||
newReturnedColumns.push_back(newSC);
|
newReturnedColumns.push_back(newSC);
|
||||||
}
|
}
|
||||||
// RC doesn't belong to any of the new derived tables
|
// RC doesn't belong to any of the new derived tables
|
||||||
@@ -413,8 +438,9 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
for (auto* sc : rc->simpleColumnList())
|
for (auto* sc : rc->simpleColumnList())
|
||||||
{
|
{
|
||||||
// TODO add method to SC to get table alias
|
// TODO add method to SC to get table alias
|
||||||
// auto scTableAliasOpt = sc->singleTable();
|
|
||||||
auto tableAliasIt = tableAliasMap.find(*sc->singleTable());
|
auto tableAliasIt = tableAliasMap.find(*sc->singleTable());
|
||||||
|
auto tableAliasToSCPositionsIt = tableAliasToSCPositionsMap.find(*sc->singleTable());
|
||||||
|
|
||||||
// Need a method to replace original SCs in the SClist
|
// Need a method to replace original SCs in the SClist
|
||||||
if (tableAliasIt != tableAliasMap.end())
|
if (tableAliasIt != tableAliasMap.end())
|
||||||
{
|
{
|
||||||
@@ -422,7 +448,21 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
sc->tableName("");
|
sc->tableName("");
|
||||||
sc->schemaName("");
|
sc->schemaName("");
|
||||||
sc->tableAlias(newTableAlias);
|
sc->tableAlias(newTableAlias);
|
||||||
sc->colPosition(colPosition++);
|
|
||||||
|
auto& [unused, SCAliasToPosCounterMap, currentColPosition] = tableAliasToSCPositionsIt->second;
|
||||||
|
auto it = SCAliasToPosCounterMap.find(sc->columnName());
|
||||||
|
if (it == SCAliasToPosCounterMap.end())
|
||||||
|
{
|
||||||
|
SCAliasToPosCounterMap.insert({sc->columnName(), currentColPosition++});
|
||||||
|
std::cout << " 2nd case new column in the map colPosition " << SCAliasToPosCounterMap[sc->columnName()] << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " 2nd case reusing column from the map colPosition " << SCAliasToPosCounterMap[sc->columnName()] << std::endl;
|
||||||
|
}
|
||||||
|
assert(SCAliasToPosCounterMap[sc->columnName()] == colPosition);
|
||||||
|
sc->colPosition(SCAliasToPosCounterMap[sc->columnName()]);
|
||||||
|
// sc->colPosition(colPosition++);
|
||||||
}
|
}
|
||||||
// do nothing with this SC
|
// do nothing with this SC
|
||||||
}
|
}
|
||||||
@@ -433,33 +473,67 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO
|
|||||||
// But this is inappropriate for some EXISTS filter and join conditions
|
// But this is inappropriate for some EXISTS filter and join conditions
|
||||||
|
|
||||||
// WIP hardcoded query with lhs,rhs being simple columns
|
// WIP hardcoded query with lhs,rhs being simple columns
|
||||||
if (csep.filters() && csep.filters()->data())
|
auto filters = csep.filters();
|
||||||
|
|
||||||
|
if (filters)
|
||||||
{
|
{
|
||||||
auto* left = dynamic_cast<execplan::SimpleFilter*>(csep.filters()->data());
|
std::vector<execplan::SimpleColumn*> simpleColumns;
|
||||||
if (left)
|
filters->walk(execplan::getSimpleCols, &simpleColumns);
|
||||||
|
for (auto* sc : simpleColumns)
|
||||||
{
|
{
|
||||||
auto* lhs = left->lhs()->clone();
|
std::cout << " filters SC " << sc->toString() << std::endl;
|
||||||
if (lhs)
|
auto tableAliasToSCPositionsIt = tableAliasToSCPositionsMap.find(*sc->singleTable());
|
||||||
|
if (tableAliasToSCPositionsIt != tableAliasToSCPositionsMap.end())
|
||||||
{
|
{
|
||||||
auto* lhsSC = dynamic_cast<execplan::SimpleColumn*>(lhs);
|
auto& [newTableAlias, SCAliasToPosCounterMap, currentColPosition] = tableAliasToSCPositionsIt->second;
|
||||||
if (lhsSC)
|
std::cout << " filters map colPosition " << SCAliasToPosCounterMap[sc->columnName()] << std::endl;
|
||||||
|
auto it = SCAliasToPosCounterMap.find(sc->columnName());
|
||||||
|
if (it == SCAliasToPosCounterMap.end())
|
||||||
{
|
{
|
||||||
auto newTableAlias =
|
SCAliasToPosCounterMap.insert({sc->columnName(), currentColPosition++});
|
||||||
tableAliasMap.find({lhsSC->schemaName(), lhsSC->tableName(), lhsSC->tableAlias(), "", false});
|
|
||||||
// WIP Leak loosing previous lhs
|
|
||||||
if (newTableAlias != tableAliasMap.end())
|
|
||||||
{
|
|
||||||
lhsSC->tableName("");
|
|
||||||
lhsSC->schemaName("");
|
|
||||||
lhsSC->tableAlias(newTableAlias->second.first);
|
|
||||||
lhsSC->colPosition(0);
|
|
||||||
left->lhs(lhs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
sc->colPosition(SCAliasToPosCounterMap[sc->columnName()]);
|
||||||
|
|
||||||
|
sc->tableName("");
|
||||||
|
sc->schemaName("");
|
||||||
|
sc->tableAlias(newTableAlias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (csep.filters() && csep.filters()->data())
|
||||||
|
// {
|
||||||
|
// auto* left = dynamic_cast<execplan::SimpleFilter*>(csep.filters()->data());
|
||||||
|
// if (left)
|
||||||
|
// {
|
||||||
|
// auto* lhs = left->lhs()->clone();
|
||||||
|
// if (lhs)
|
||||||
|
// {
|
||||||
|
// auto* lhsSC = dynamic_cast<execplan::SimpleColumn*>(lhs);
|
||||||
|
// if (lhsSC)
|
||||||
|
// {
|
||||||
|
// auto newTableAlias =
|
||||||
|
// tableAliasMap.find({lhsSC->schemaName(), lhsSC->tableName(), lhsSC->tableAlias(), "", false});
|
||||||
|
// // WIP Leak loosing previous lhs
|
||||||
|
// if (newTableAlias != tableAliasMap.end())
|
||||||
|
// {
|
||||||
|
// lhsSC->tableName("");
|
||||||
|
// lhsSC->schemaName("");
|
||||||
|
// lhsSC->tableAlias(newTableAlias->second.first);
|
||||||
|
// lhsSC->colPosition(0);
|
||||||
|
// left->lhs(lhs);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ struct TableAliasLessThan
|
|||||||
using NewTableAliasAndColumnPosCounter = std::pair<std::string, size_t>;
|
using NewTableAliasAndColumnPosCounter = std::pair<std::string, size_t>;
|
||||||
using TableAliasMap = std::map<execplan::CalpontSystemCatalog::TableAliasName,
|
using TableAliasMap = std::map<execplan::CalpontSystemCatalog::TableAliasName,
|
||||||
NewTableAliasAndColumnPosCounter, TableAliasLessThan>;
|
NewTableAliasAndColumnPosCounter, TableAliasLessThan>;
|
||||||
|
using SCAliasToPosCounterMap = std::map<std::string, size_t>;
|
||||||
|
using TableAliasToNewAliasAndSCPositionsMap =
|
||||||
|
std::map<execplan::CalpontSystemCatalog::TableAliasName,
|
||||||
|
std::tuple<std::string, SCAliasToPosCounterMap, size_t>, TableAliasLessThan>;
|
||||||
|
|
||||||
bool parallelCESFilter(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
bool parallelCESFilter(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
||||||
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
||||||
|
|||||||
@@ -1133,4 +1133,24 @@ GROUP BY s1.col2;
|
|||||||
фичи:
|
фичи:
|
||||||
- собрать первые колонки ключей, по которым есть статистика и сделать из них SC, которые можно использовать - extractColumnStatistics ходит по table, а не по ifp
|
- собрать первые колонки ключей, по которым есть статистика и сделать из них SC, которые можно использовать - extractColumnStatistics ходит по table, а не по ifp
|
||||||
- запрос `select l_suppkey from lineitem limit 10;`
|
- запрос `select l_suppkey from lineitem limit 10;`
|
||||||
- Статистика собирается из таблиц, нужно добавить SC-кандидаты в статистику
|
- Статистика собирается из таблиц, нужно добавить SC-кандидаты в статистику
|
||||||
|
|
||||||
|
|
||||||
|
Про фильтры MCOL-6117
|
||||||
|
- Рассмотрев, что фильтр содержит выражения из:
|
||||||
|
- колонок, прендалежищих не затронутым таблицам (гр 1)
|
||||||
|
- выражений, содержащих колонки только незатронутых таблиц (гр 1)
|
||||||
|
|
||||||
|
- колонок затронутых таблиц SC (гр 2)
|
||||||
|
- замапить на SC соответствующих derived
|
||||||
|
- выражений, содержащих колонки только затронутых таблиц (гр 2)
|
||||||
|
- замапить SC затронутых таблиц на SC derived
|
||||||
|
- ОПТ замапить на SC затронутых таблиц, если нет AC в поддереве
|
||||||
|
- выражений, содержащих колонки затронутых таблиц и колонок не затронутых таблиц (гр 2)
|
||||||
|
- замапить SC затронутых таблиц на SC derived
|
||||||
|
- применить правила маппинга SC в выражении фильтра
|
||||||
|
- прогнать существующее правило проброса условий вниз
|
||||||
|
- если не получится, то клонить дерево фильтра и заменять нерелевантные части на true
|
||||||
|
- добавить правило очистки от constant true в дереве
|
||||||
|
- правило проброса условий вниз работает для derived, но не работает для UNION
|
||||||
|
- оптимизация добавить правило проброса условий в UNION
|
||||||
|
|||||||
Reference in New Issue
Block a user