From 98cb6dddeea43ce6ddbe26153087f8167f3f245b Mon Sep 17 00:00:00 2001 From: drrtuy Date: Mon, 16 Jun 2025 13:59:29 +0000 Subject: [PATCH] feat(optimizer): replace simple walk with iterative DFS with convergence --- dbcon/execplan/calpontselectexecutionplan.h | 3 +++ dbcon/mysql/rulebased_optimizer.cpp | 21 ++++++++++++++++++--- dbcon/mysql/rulebased_optimizer.h | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dbcon/execplan/calpontselectexecutionplan.h b/dbcon/execplan/calpontselectexecutionplan.h index 0914acb86..e9425ed45 100644 --- a/dbcon/execplan/calpontselectexecutionplan.h +++ b/dbcon/execplan/calpontselectexecutionplan.h @@ -159,6 +159,9 @@ class CalpontSelectExecutionPlan : public CalpontExecutionPlan */ ~CalpontSelectExecutionPlan() override; + /** + * Clones this CSEP without recursive selects for optimizer purposes + */ execplan::SCSEP cloneWORecursiveSelects(); /** * Access and mutator methods diff --git a/dbcon/mysql/rulebased_optimizer.cpp b/dbcon/mysql/rulebased_optimizer.cpp index d3de06055..4e9c22b96 100644 --- a/dbcon/mysql/rulebased_optimizer.cpp +++ b/dbcon/mysql/rulebased_optimizer.cpp @@ -21,6 +21,7 @@ namespace optimizer { +// Apply a list of rules to a CSEP bool optimizeCSEPWithRules(execplan::CalpontSelectExecutionPlan& root, const std::vector& rules) { bool changed = false; @@ -31,6 +32,7 @@ bool optimizeCSEPWithRules(execplan::CalpontSelectExecutionPlan& root, const std return changed; } +// high level API call for optimizer bool optimizeCSEP(execplan::CalpontSelectExecutionPlan& root) { optimizer::Rule parallelCES{"parallelCES", optimizer::matchParallelCES, optimizer::applyParallelCES}; @@ -40,8 +42,22 @@ bool optimizeCSEP(execplan::CalpontSelectExecutionPlan& root) return optimizeCSEPWithRules(root, rules); } -// DFS walk -bool Rule::apply(execplan::CalpontSelectExecutionPlan& csep) const +// Apply iteratively until CSEP is converged by rule +bool Rule::apply(execplan::CalpontSelectExecutionPlan& root) const +{ + bool changedThisRound = false; + bool hasBeenApplied = false; + do + { + changedThisRound = walk(root); + hasBeenApplied = changedThisRound; + } while (changedThisRound); + + return hasBeenApplied; +} + +// DFS walk to match CSEP and apply rules if match +bool Rule::walk(execplan::CalpontSelectExecutionPlan& csep) const { bool rewrite = false; @@ -78,7 +94,6 @@ bool Rule::apply(execplan::CalpontSelectExecutionPlan& csep) const return rewrite; } - bool tableIsInUnion(const execplan::CalpontSystemCatalog::TableAliasName& table, execplan::CalpontSelectExecutionPlan& csep) { return std::any_of(csep.unionVec().begin(), csep.unionVec().end(), diff --git a/dbcon/mysql/rulebased_optimizer.h b/dbcon/mysql/rulebased_optimizer.h index 65fa3f359..9296f2002 100644 --- a/dbcon/mysql/rulebased_optimizer.h +++ b/dbcon/mysql/rulebased_optimizer.h @@ -32,6 +32,7 @@ struct Rule bool (*matchRule)(execplan::CalpontSelectExecutionPlan&); void (*applyRule)(execplan::CalpontSelectExecutionPlan&); bool apply(execplan::CalpontSelectExecutionPlan& csep) const; + bool walk(execplan::CalpontSelectExecutionPlan& csep) const; }; bool matchParallelCES(execplan::CalpontSelectExecutionPlan& csep);