diff --git a/dbcon/execplan/parsetree.h b/dbcon/execplan/parsetree.h index b068129a1..2cc2c3b13 100644 --- a/dbcon/execplan/parsetree.h +++ b/dbcon/execplan/parsetree.h @@ -612,7 +612,6 @@ inline ParseTree& ParseTree::operator=(const ParseTree& rhs) { if (this != &rhs) { - // copyTree(*this, rhs); copyTree(rhs); } diff --git a/dbcon/mysql/ha_mcs_execplan.cpp b/dbcon/mysql/ha_mcs_execplan.cpp index 66934a7c3..e143a38ec 100644 --- a/dbcon/mysql/ha_mcs_execplan.cpp +++ b/dbcon/mysql/ha_mcs_execplan.cpp @@ -7596,8 +7596,11 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP& // Derived table projection list optimization. derivedTableOptimization(&gwi, csep); + { 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); if (csep->traceOn() && csepWasOptimized) { diff --git a/dbcon/mysql/rbo_apply_parallel_ces.cpp b/dbcon/mysql/rbo_apply_parallel_ces.cpp index 7b257c78e..f326251d0 100644 --- a/dbcon/mysql/rbo_apply_parallel_ces.cpp +++ b/dbcon/mysql/rbo_apply_parallel_ces.cpp @@ -345,6 +345,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList; optimizer::TableAliasMap tableAliasMap; bool ruleHasBeenApplied = false; + optimizer::TableAliasToNewAliasAndSCPositionsMap tableAliasToSCPositionsMap; 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::to_string(ctx.uniqueId); tableAliasMap.insert({table, {tableAlias, 0}}); + tableAliasToSCPositionsMap.insert({table, {tableAlias, {}, 0}}); execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, ""); 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 << " alias " << sameTableAliasOpt->alias << std::endl; auto tableAliasIt = tableAliasMap.find(*sameTableAliasOpt); + auto tableAliasToSCPositionsIt = tableAliasToSCPositionsMap.find(*sameTableAliasOpt); if (tableAliasIt != tableAliasMap.end()) { std::cout << "Replacing RC with new SC" << std::endl; @@ -395,8 +398,30 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO newSC->tableName(""); newSC->schemaName(""); newSC->tableAlias(newTableAlias); - newSC->colPosition(colPosition++); newSC->alias(rc->alias()); + + auto* sc = dynamic_cast(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); } // 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()) { // TODO add method to SC to get table alias - // auto scTableAliasOpt = sc->singleTable(); auto tableAliasIt = tableAliasMap.find(*sc->singleTable()); + auto tableAliasToSCPositionsIt = tableAliasToSCPositionsMap.find(*sc->singleTable()); + // Need a method to replace original SCs in the SClist if (tableAliasIt != tableAliasMap.end()) { @@ -422,7 +448,21 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO sc->tableName(""); sc->schemaName(""); 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 } @@ -433,33 +473,67 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBO // But this is inappropriate for some EXISTS filter and join conditions // 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(csep.filters()->data()); - if (left) + std::vector simpleColumns; + filters->walk(execplan::getSimpleCols, &simpleColumns); + for (auto* sc : simpleColumns) { - auto* lhs = left->lhs()->clone(); - if (lhs) + std::cout << " filters SC " << sc->toString() << std::endl; + auto tableAliasToSCPositionsIt = tableAliasToSCPositionsMap.find(*sc->singleTable()); + if (tableAliasToSCPositionsIt != tableAliasToSCPositionsMap.end()) { - auto* lhsSC = dynamic_cast(lhs); - if (lhsSC) + auto& [newTableAlias, SCAliasToPosCounterMap, currentColPosition] = tableAliasToSCPositionsIt->second; + std::cout << " filters map colPosition " << SCAliasToPosCounterMap[sc->columnName()] << std::endl; + auto it = SCAliasToPosCounterMap.find(sc->columnName()); + if (it == SCAliasToPosCounterMap.end()) { - 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); - } + SCAliasToPosCounterMap.insert({sc->columnName(), currentColPosition++}); } + else + { + // noop + } + sc->colPosition(SCAliasToPosCounterMap[sc->columnName()]); + + sc->tableName(""); + sc->schemaName(""); + sc->tableAlias(newTableAlias); } } } + // if (csep.filters() && csep.filters()->data()) + // { + // auto* left = dynamic_cast(csep.filters()->data()); + // if (left) + // { + // auto* lhs = left->lhs()->clone(); + // if (lhs) + // { + // auto* lhsSC = dynamic_cast(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); // Replace table list with new table list populated with union units csep.tableList(newTableList); diff --git a/dbcon/mysql/rbo_apply_parallel_ces.h b/dbcon/mysql/rbo_apply_parallel_ces.h index 1f0f4440b..5c8589b1b 100644 --- a/dbcon/mysql/rbo_apply_parallel_ces.h +++ b/dbcon/mysql/rbo_apply_parallel_ces.h @@ -57,6 +57,10 @@ struct TableAliasLessThan using NewTableAliasAndColumnPosCounter = std::pair; using TableAliasMap = std::map; +using SCAliasToPosCounterMap = std::map; +using TableAliasToNewAliasAndSCPositionsMap = + std::map, TableAliasLessThan>; bool parallelCESFilter(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx); bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx); diff --git a/docs/QA_parallel.md b/docs/QA_parallel.md index c8cd5ce76..3882803bf 100644 --- a/docs/QA_parallel.md +++ b/docs/QA_parallel.md @@ -1133,4 +1133,24 @@ GROUP BY s1.col2; фичи: - собрать первые колонки ключей, по которым есть статистика и сделать из них SC, которые можно использовать - extractColumnStatistics ходит по table, а не по ifp - запрос `select l_suppkey from lineitem limit 10;` -- Статистика собирается из таблиц, нужно добавить SC-кандидаты в статистику \ No newline at end of file +- Статистика собирается из таблиц, нужно добавить 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