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): rule matcher has been replaced with csep filter for a rule to relax rule filter predicates and endless loop has been fixed in pushdown predicates.
This commit is contained in:
@@ -44,6 +44,7 @@ set(libcalmysql_SRCS
|
||||
columnstore_dataload.cpp
|
||||
rulebased_optimizer.cpp
|
||||
rbo_apply_parallel_ces.cpp
|
||||
rbo_predicate_pushdown.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(ha_mcs.cpp PROPERTIES COMPILE_FLAGS "-fno-implicit-templates")
|
||||
|
||||
@@ -54,7 +54,7 @@ bool tableIsInUnion(const execplan::CalpontSystemCatalog::TableAliasName& table,
|
||||
});
|
||||
}
|
||||
|
||||
bool matchParallelCES(execplan::CalpontSelectExecutionPlan& csep)
|
||||
bool parallelCESFilter(execplan::CalpontSelectExecutionPlan& csep)
|
||||
{
|
||||
auto tables = csep.tableList();
|
||||
// This is leaf and there are no other tables at this level in neither UNION, nor derived table.
|
||||
@@ -198,12 +198,13 @@ execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(
|
||||
|
||||
return unionVec;
|
||||
}
|
||||
void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx)
|
||||
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx)
|
||||
{
|
||||
auto tables = csep.tableList();
|
||||
execplan::CalpontSelectExecutionPlan::TableList newTableList;
|
||||
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
||||
execplan::CalpontSelectExecutionPlan::ReturnedColumnList newReturnedColumns;
|
||||
bool ruleHasBeenApplied = false;
|
||||
|
||||
// ATM Must be only 1 table
|
||||
for (auto& table : tables)
|
||||
@@ -246,6 +247,7 @@ void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
|
||||
// Remove the filters as they were pushed down to union units
|
||||
// This is inappropriate for EXISTS filter and join conditions
|
||||
derivedSCEP->filters(nullptr);
|
||||
ruleHasBeenApplied = true;
|
||||
}
|
||||
}
|
||||
// Remove the filters if necessary using csep.filters(nullptr) as they were pushed down to union units
|
||||
@@ -255,6 +257,7 @@ void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
|
||||
// Replace table list with new table list populated with union units
|
||||
csep.tableList(newTableList);
|
||||
csep.returnedCols(newReturnedColumns);
|
||||
return ruleHasBeenApplied;
|
||||
}
|
||||
|
||||
} // namespace optimizer
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
#include "rulebased_optimizer.h"
|
||||
|
||||
namespace optimizer {
|
||||
bool matchParallelCES(execplan::CalpontSelectExecutionPlan& csep);
|
||||
void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
||||
bool parallelCESFilter(execplan::CalpontSelectExecutionPlan& csep);
|
||||
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
||||
}
|
||||
@@ -29,13 +29,16 @@
|
||||
namespace optimizer
|
||||
{
|
||||
|
||||
bool matchPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep)
|
||||
using DerivedToFiltersMap = std::map<std::string, execplan::ParseTree*>;
|
||||
|
||||
bool predicatePushdownFilter(execplan::CalpontSelectExecutionPlan& csep)
|
||||
{
|
||||
// The original rule match contains questionable decision to filter out
|
||||
// queries that contains any UNION UNIT with only derived tables.
|
||||
// See ha_from_sub.cpp before MCS 23.10.7 for more details and @bug6156.
|
||||
// All tables are derived thus nothing to optimize.
|
||||
return !csep.tableList().empty();
|
||||
return !
|
||||
csep.tableList().empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +76,7 @@ void setDerivedTable(execplan::ParseTree* n)
|
||||
}
|
||||
}
|
||||
|
||||
execplan::ParseTree* setDerivedFilter(cal_impl_if::gp_walk_info* gwip, execplan::ParseTree*& n, map<string, execplan::ParseTree*>& filterMap,
|
||||
execplan::ParseTree* setDerivedFilter(cal_impl_if::gp_walk_info* gwip, execplan::ParseTree*& n, DerivedToFiltersMap& filterMap,
|
||||
const execplan::CalpontSelectExecutionPlan::SelectList& derivedTbList)
|
||||
{
|
||||
if (!(n->derivedTable().empty()))
|
||||
@@ -99,11 +102,11 @@ execplan::ParseTree* setDerivedFilter(cal_impl_if::gp_walk_info* gwip, execplan:
|
||||
|
||||
// 2. push the filter to the derived table filter stack, or 'and' with
|
||||
// the filters in the stack
|
||||
map<string, execplan::ParseTree*>::iterator mapIter = filterMap.find(n->derivedTable());
|
||||
auto mapIter = filterMap.find(n->derivedTable());
|
||||
|
||||
if (mapIter == filterMap.end())
|
||||
{
|
||||
filterMap.insert(pair<string, execplan::ParseTree*>(n->derivedTable(), n));
|
||||
filterMap.insert({n->derivedTable(), n});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -141,7 +144,7 @@ execplan::ParseTree* setDerivedFilter(cal_impl_if::gp_walk_info* gwip, execplan:
|
||||
return n;
|
||||
}
|
||||
|
||||
void applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx)
|
||||
bool applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx)
|
||||
{
|
||||
/*
|
||||
* @bug5635. Move filters that only belongs to a derived table to inside the derived table.
|
||||
@@ -158,8 +161,9 @@ void applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, RBOptimi
|
||||
* stacked filter needs to be reset (not null)
|
||||
*/
|
||||
execplan::ParseTree* pt = csep.filters();
|
||||
map<string, execplan::ParseTree*> derivedTbFilterMap;
|
||||
DerivedToFiltersMap derivedTbFilterMap;
|
||||
auto& derivedTbList = csep.derivedTableList();
|
||||
bool hasBeenApplied = false;
|
||||
|
||||
if (pt)
|
||||
{
|
||||
@@ -171,13 +175,11 @@ void applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, RBOptimi
|
||||
// AND the filters of individual stack to the derived table filter tree
|
||||
// @todo union filters.
|
||||
// @todo outer join complication
|
||||
map<string, execplan::ParseTree*>::iterator mapIt;
|
||||
|
||||
for (uint i = 0; i < derivedTbList.size(); i++)
|
||||
{
|
||||
execplan::CalpontSelectExecutionPlan* plan = dynamic_cast<execplan::CalpontSelectExecutionPlan*>(derivedTbList[i].get());
|
||||
execplan::CalpontSelectExecutionPlan::ReturnedColumnList derivedColList = plan->returnedCols();
|
||||
mapIt = derivedTbFilterMap.find(plan->derivedTbAlias());
|
||||
auto mapIt = derivedTbFilterMap.find(plan->derivedTbAlias());
|
||||
|
||||
if (mapIt != derivedTbFilterMap.end())
|
||||
{
|
||||
@@ -225,12 +227,17 @@ void applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, RBOptimi
|
||||
unionPlan->filters(mainFilterForUnion);
|
||||
}
|
||||
}
|
||||
hasBeenApplied = true;
|
||||
}
|
||||
}
|
||||
|
||||
// clean derivedTbFilterMap because all the filters are copied
|
||||
for (mapIt = derivedTbFilterMap.begin(); mapIt != derivedTbFilterMap.end(); ++mapIt)
|
||||
delete (*mapIt).second;
|
||||
for (auto mapIt = derivedTbFilterMap.begin(); mapIt != derivedTbFilterMap.end(); ++mapIt)
|
||||
{
|
||||
delete (*mapIt).second;
|
||||
}
|
||||
|
||||
return hasBeenApplied;
|
||||
}
|
||||
|
||||
} // namespace optimizer
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
#include "rulebased_optimizer.h"
|
||||
|
||||
namespace optimizer {
|
||||
bool matchPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep);
|
||||
void applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
||||
bool predicatePushdownFilter(execplan::CalpontSelectExecutionPlan& csep);
|
||||
bool applyPredicatePushdown(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx);
|
||||
}
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "predicateoperator.h"
|
||||
#include "simplefilter.h"
|
||||
#include "rbo_apply_parallel_ces.h"
|
||||
#include "rbo_predicate_pushdown.h"
|
||||
|
||||
namespace optimizer
|
||||
{
|
||||
@@ -54,12 +55,12 @@ bool optimizeCSEP(execplan::CalpontSelectExecutionPlan& root, optimizer::RBOptim
|
||||
|
||||
if (get_unstable_optimizer(&ctx.thd))
|
||||
{
|
||||
optimizer::Rule parallelCES{"parallelCES", optimizer::matchParallelCES, optimizer::applyParallelCES};
|
||||
optimizer::Rule parallelCES{"parallelCES", optimizer::parallelCESFilter, optimizer::applyParallelCES};
|
||||
rules.push_back(parallelCES);
|
||||
}
|
||||
|
||||
optimizer::Rule predicatePushdown{"predicatePushdown", optimizer::matchParallelCES,
|
||||
optimizer::applyParallelCES};
|
||||
optimizer::Rule predicatePushdown{"predicatePushdown", optimizer::predicatePushdownFilter,
|
||||
optimizer::applyPredicatePushdown};
|
||||
rules.push_back(predicatePushdown);
|
||||
|
||||
return optimizeCSEPWithRules(root, rules, ctx);
|
||||
@@ -114,7 +115,7 @@ bool Rule::walk(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimiz
|
||||
}
|
||||
|
||||
// Walk nested subselect in filters, e.g. SEMI-JOIN
|
||||
for (auto& subselect : csep.subSelectList())
|
||||
for (auto& subselect : current->subSelectList())
|
||||
{
|
||||
auto* subselectPtr = dynamic_cast<execplan::CalpontSelectExecutionPlan*>(subselect.get());
|
||||
if (subselectPtr)
|
||||
@@ -125,11 +126,10 @@ bool Rule::walk(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimiz
|
||||
|
||||
// TODO add walking nested subselect in projection. See CSEP::fSelectSubList
|
||||
|
||||
if (matchRule(*current))
|
||||
if (mayApply(*current))
|
||||
{
|
||||
applyRule(*current, ctx);
|
||||
rewrite = applyRule(*current, ctx);
|
||||
++ctx.uniqueId;
|
||||
rewrite = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,14 +42,16 @@ public:
|
||||
|
||||
struct Rule
|
||||
{
|
||||
using RuleMatcher = bool (*)(execplan::CalpontSelectExecutionPlan&);
|
||||
using RuleApplier = void (*)(execplan::CalpontSelectExecutionPlan&, RBOptimizerContext&);
|
||||
// returns true if rule may be applied
|
||||
using RuleApplierFilter = bool (*)(execplan::CalpontSelectExecutionPlan&);
|
||||
// returns true if rule was applied
|
||||
using RuleApplier = bool (*)(execplan::CalpontSelectExecutionPlan&, RBOptimizerContext&);
|
||||
|
||||
Rule(std::string&& name, RuleMatcher matchRule, RuleApplier applyRule)
|
||||
: name(name), matchRule(matchRule), applyRule(applyRule) {};
|
||||
Rule(std::string&& name, RuleApplierFilter mayApply, RuleApplier applyRule)
|
||||
: name(name), mayApply(mayApply), applyRule(applyRule) {};
|
||||
|
||||
std::string name;
|
||||
RuleMatcher matchRule;
|
||||
RuleApplierFilter mayApply;
|
||||
RuleApplier applyRule;
|
||||
// TODO Wrap CSEP into Nodes to be able to navigate up and down the tree and remove this flag
|
||||
bool applyOnlyOnce = true;
|
||||
|
||||
Reference in New Issue
Block a user