diff --git a/Cargo.lock b/Cargo.lock index 1d794d06d405..2efc711ca538 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2057,8 +2057,6 @@ dependencies = [ "educe", "globiter", "itertools", - "num-derive", - "num-traits", "once_cell", "opendal", "ordered-float 3.4.0", diff --git a/src/query/sql/Cargo.toml b/src/query/sql/Cargo.toml index fc178388c8df..945bb74ff588 100644 --- a/src/query/sql/Cargo.toml +++ b/src/query/sql/Cargo.toml @@ -48,8 +48,6 @@ dashmap = "5.4" educe = "0.4" globiter = "0.1" itertools = "0.10.5" -num-derive = "0.3.3" -num-traits = "0.2.15" once_cell = "1.15.0" opendal = { workspace = true } ordered-float = { workspace = true } diff --git a/src/query/sql/src/planner/optimizer/cascades/cascade.rs b/src/query/sql/src/planner/optimizer/cascades/cascade.rs index a0a9be82ba34..057040e962b2 100644 --- a/src/query/sql/src/planner/optimizer/cascades/cascade.rs +++ b/src/query/sql/src/planner/optimizer/cascades/cascade.rs @@ -18,8 +18,9 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::ErrorCode; use common_exception::Result; +use roaring::RoaringBitmap; -use super::explore_rules::get_explore_rule_set; +use super::explore_rules::calc_explore_rule_set; use crate::optimizer::cascades::scheduler::Scheduler; use crate::optimizer::cascades::tasks::OptimizeGroupTask; use crate::optimizer::cascades::tasks::Task; @@ -29,36 +30,36 @@ use crate::optimizer::cost::DefaultCostModel; use crate::optimizer::format::display_memo; use crate::optimizer::memo::Memo; use crate::optimizer::rule::TransformResult; -use crate::optimizer::RuleSet; use crate::optimizer::SExpr; use crate::IndexType; -use crate::MetadataRef; /// A cascades-style search engine to enumerate possible alternations of a relational expression and /// find the optimal one. pub struct CascadesOptimizer { - pub(crate) memo: Memo, - pub(crate) cost_model: Box, + pub memo: Memo, + pub explore_rule_set: roaring::RoaringBitmap, + + pub cost_model: Box, + /// group index -> best cost context - pub(crate) best_cost_map: HashMap, - pub(crate) explore_rule_set: RuleSet, - pub(crate) metadata: MetadataRef, + pub best_cost_map: HashMap, + _ctx: Arc, } impl CascadesOptimizer { - pub fn create(ctx: Arc, metadata: MetadataRef) -> Result { + pub fn create(ctx: Arc) -> Result { let enable_bushy_join = ctx.get_settings().get_enable_bushy_join()? != 0; let explore_rule_set = if ctx.get_settings().get_enable_cbo()? { - get_explore_rule_set(enable_bushy_join) + calc_explore_rule_set(enable_bushy_join) } else { - RuleSet::create() + RoaringBitmap::new() }; Ok(CascadesOptimizer { memo: Memo::create(), cost_model: Box::new(DefaultCostModel), best_cost_map: HashMap::new(), + _ctx: ctx, explore_rule_set, - metadata, }) } diff --git a/src/query/sql/src/planner/optimizer/cascades/explore_rules.rs b/src/query/sql/src/planner/optimizer/cascades/explore_rules.rs index a60bb32b6981..5e004940db88 100644 --- a/src/query/sql/src/planner/optimizer/cascades/explore_rules.rs +++ b/src/query/sql/src/planner/optimizer/cascades/explore_rules.rs @@ -12,30 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. +use roaring::RoaringBitmap; + use crate::optimizer::RuleID; -use crate::optimizer::RuleSet; -pub fn get_explore_rule_set(enable_bushy_join: bool) -> RuleSet { +pub fn calc_explore_rule_set(enable_bushy_join: bool) -> RoaringBitmap { if enable_bushy_join { - rule_set_rs_b2() + calc_join_rule_set_rs_b2() } else { - rule_set_rs_l1() + calc_join_rule_set_rs_l1() } } /// Get rule set of join order RS-B2, which may generate bushy trees. /// Read paper "The Complexity of Transformation-Based Join Enumeration" for more details. -fn rule_set_rs_b2() -> RuleSet { - RuleSet::create_with_ids(vec![ - RuleID::CommuteJoin, - RuleID::LeftAssociateJoin, - RuleID::RightAssociateJoin, - RuleID::ExchangeJoin, - ]) +fn calc_join_rule_set_rs_b2() -> RoaringBitmap { + (RuleID::CommuteJoin as u32..RuleID::CommuteJoinBaseTable as u32).collect::() } /// Get rule set of join order RS-L1, which will only generate left-deep trees. /// Read paper "The Complexity of Transformation-Based Join Enumeration" for more details. -fn rule_set_rs_l1() -> RuleSet { - RuleSet::create_with_ids(vec![RuleID::CommuteJoinBaseTable, RuleID::LeftExchangeJoin]) +fn calc_join_rule_set_rs_l1() -> RoaringBitmap { + (RuleID::CommuteJoinBaseTable as u32..RuleID::RightExchangeJoin as u32) + .collect::() } diff --git a/src/query/sql/src/planner/optimizer/cascades/tasks/apply_rule.rs b/src/query/sql/src/planner/optimizer/cascades/tasks/apply_rule.rs index b188295c9701..401a0c7f09fd 100644 --- a/src/query/sql/src/planner/optimizer/cascades/tasks/apply_rule.rs +++ b/src/query/sql/src/planner/optimizer/cascades/tasks/apply_rule.rs @@ -58,7 +58,7 @@ impl ApplyRuleTask { let group = optimizer.memo.group(self.target_group_index)?; let m_expr = group.m_expr(self.m_expr_index)?; let mut state = TransformResult::new(); - let rule = RuleFactory::create_rule(self.rule_id, optimizer.metadata.clone())?; + let rule = RuleFactory::create().create_rule(self.rule_id, None)?; m_expr.apply_rule(&optimizer.memo, &rule, &mut state)?; optimizer.insert_from_transform_state(self.target_group_index, state)?; diff --git a/src/query/sql/src/planner/optimizer/cascades/tasks/explore_expr.rs b/src/query/sql/src/planner/optimizer/cascades/tasks/explore_expr.rs index d42315acd19f..a4859bf3a1d0 100644 --- a/src/query/sql/src/planner/optimizer/cascades/tasks/explore_expr.rs +++ b/src/query/sql/src/planner/optimizer/cascades/tasks/explore_expr.rs @@ -22,6 +22,10 @@ use super::Task; use crate::optimizer::cascades::scheduler::Scheduler; use crate::optimizer::cascades::tasks::SharedCounter; use crate::optimizer::cascades::CascadesOptimizer; +use crate::optimizer::RuleID; +use crate::optimizer::RULE_FACTORY; +use crate::plans::Operator; +use crate::plans::RelOperator; use crate::IndexType; #[derive(Clone, Copy, Debug)] @@ -140,6 +144,18 @@ impl ExploreExprTask { } } + fn calc_operator_rule_set( + &self, + optimizer: &CascadesOptimizer, + operator: &RelOperator, + ) -> roaring::RoaringBitmap { + unsafe { + operator.exploration_candidate_rules() + & (&RULE_FACTORY.exploration_rules) + & (&optimizer.explore_rule_set) + } + } + fn explore_self( &mut self, optimizer: &mut CascadesOptimizer, @@ -149,11 +165,11 @@ impl ExploreExprTask { .memo .group(self.group_index)? .m_expr(self.m_expr_index)?; - let rule_set = &optimizer.explore_rule_set; + let rule_set = self.calc_operator_rule_set(optimizer, &m_expr.plan); for rule_id in rule_set.iter() { let apply_rule_task = ApplyRuleTask::with_parent( - rule_id, + unsafe { std::mem::transmute::(rule_id as u8) }, m_expr.group_index, m_expr.index, &self.ref_count, diff --git a/src/query/sql/src/planner/optimizer/heuristic/heuristic.rs b/src/query/sql/src/planner/optimizer/heuristic/heuristic.rs index f5e60d4ab0e2..1c6947fb6a52 100644 --- a/src/query/sql/src/planner/optimizer/heuristic/heuristic.rs +++ b/src/query/sql/src/planner/optimizer/heuristic/heuristic.rs @@ -20,37 +20,45 @@ use once_cell::sync::Lazy; use super::prune_unused_columns::UnusedColumnPruner; use crate::optimizer::heuristic::decorrelate::decorrelate_subquery; +use crate::optimizer::rule::RulePtr; use crate::optimizer::rule::TransformResult; use crate::optimizer::ColumnSet; -use crate::optimizer::RuleFactory; use crate::optimizer::RuleID; use crate::optimizer::SExpr; +use crate::optimizer::RULE_FACTORY; +use crate::plans::Operator; +use crate::plans::RelOperator; use crate::BindContext; use crate::MetadataRef; pub static DEFAULT_REWRITE_RULES: Lazy> = Lazy::new(|| { vec![ + // Filter RuleID::NormalizeDisjunctiveFilter, RuleID::NormalizeScalarFilter, RuleID::EliminateFilter, - RuleID::EliminateEvalScalar, RuleID::MergeFilter, - RuleID::MergeEvalScalar, RuleID::PushDownFilterUnion, RuleID::PushDownFilterAggregate, + RuleID::PushDownFilterSort, + RuleID::PushDownFilterEvalScalar, + RuleID::PushDownFilterJoin, + RuleID::PushDownFilterScan, + // EvalScalar + RuleID::EliminateEvalScalar, + RuleID::MergeEvalScalar, + // Limit RuleID::PushDownLimitUnion, RuleID::RulePushDownLimitExpression, RuleID::PushDownLimitSort, RuleID::PushDownLimitAggregate, RuleID::PushDownLimitOuterJoin, RuleID::PushDownLimitScan, - RuleID::PushDownFilterSort, - RuleID::PushDownFilterEvalScalar, - RuleID::PushDownFilterJoin, + // Agg RuleID::FoldCountAggregate, RuleID::SplitAggregate, - RuleID::PushDownFilterScan, RuleID::PushDownPrewhere, /* PushDownPrwhere should be after all rules except PushDownFilterScan */ + // Sort RuleID::PushDownSortScan, // PushDownFilterScan should be after PushDownPrewhere ] }); @@ -113,13 +121,27 @@ impl HeuristicOptimizer { Ok(result) } + fn calc_operator_rule_set(&self, operator: &RelOperator) -> roaring::RoaringBitmap { + unsafe { operator.transformation_candidate_rules() & (&RULE_FACTORY.transformation_rules) } + } + + fn get_rule(&self, rule_id: u32) -> Result { + unsafe { + RULE_FACTORY.create_rule( + DEFAULT_REWRITE_RULES[rule_id as usize], + Some(self.metadata.clone()), + ) + } + } + /// Try to apply the rules to the expression. /// Return the final result that no rule can be applied. fn apply_transform_rules(&self, s_expr: &SExpr) -> Result { let mut s_expr = s_expr.clone(); + let rule_set = self.calc_operator_rule_set(&s_expr.plan); - for rule_id in DEFAULT_REWRITE_RULES.iter() { - let rule = RuleFactory::create_rule(*rule_id, self.metadata.clone())?; + for rule_id in rule_set.iter() { + let rule = self.get_rule(rule_id)?; let mut state = TransformResult::new(); if s_expr.match_pattern(rule.pattern()) && !s_expr.applied_rule(&rule.id()) { s_expr.set_applied_rule(&rule.id()); diff --git a/src/query/sql/src/planner/optimizer/mod.rs b/src/query/sql/src/planner/optimizer/mod.rs index 6caf05ed70c3..81caf6244e52 100644 --- a/src/query/sql/src/planner/optimizer/mod.rs +++ b/src/query/sql/src/planner/optimizer/mod.rs @@ -43,4 +43,5 @@ pub use rule::try_push_down_filter_join; pub use rule::RuleFactory; pub use rule::RuleID; pub use rule::RuleSet; +pub use rule::RULE_FACTORY; pub use s_expr::SExpr; diff --git a/src/query/sql/src/planner/optimizer/optimizer.rs b/src/query/sql/src/planner/optimizer/optimizer.rs index 9ecb5db796c2..8e887848cb31 100644 --- a/src/query/sql/src/planner/optimizer/optimizer.rs +++ b/src/query/sql/src/planner/optimizer/optimizer.rs @@ -147,9 +147,10 @@ pub fn optimize_query( ) -> Result { let contains_local_table_scan = contains_local_table_scan(&s_expr, &metadata); - let mut heuristic = HeuristicOptimizer::new(ctx.clone(), bind_context, metadata.clone()); + let mut heuristic = HeuristicOptimizer::new(ctx.clone(), bind_context, metadata); let mut result = heuristic.optimize(s_expr)?; - let mut cascades = CascadesOptimizer::create(ctx.clone(), metadata)?; + + let mut cascades = CascadesOptimizer::create(ctx.clone())?; result = cascades.optimize(result)?; // So far, we don't have ability to execute distributed query // with reading data from local tales(e.g. system tables). @@ -176,10 +177,10 @@ fn get_optimized_memo( metadata: MetadataRef, bind_context: Box, ) -> Result<(Memo, HashMap)> { - let mut heuristic = HeuristicOptimizer::new(ctx.clone(), bind_context, metadata.clone()); + let mut heuristic = HeuristicOptimizer::new(ctx.clone(), bind_context, metadata); let result = heuristic.optimize(s_expr)?; - let mut cascades = CascadesOptimizer::create(ctx, metadata)?; + let mut cascades = CascadesOptimizer::create(ctx)?; cascades.optimize(result)?; Ok((cascades.memo, cascades.best_cost_map)) } diff --git a/src/query/sql/src/planner/optimizer/rule/factory.rs b/src/query/sql/src/planner/optimizer/rule/factory.rs index 499d313306fc..c35d45ca9b27 100644 --- a/src/query/sql/src/planner/optimizer/rule/factory.rs +++ b/src/query/sql/src/planner/optimizer/rule/factory.rs @@ -13,6 +13,8 @@ // limitations under the License. use common_exception::Result; +use once_cell::sync::Lazy; +use roaring::RoaringBitmap; use super::rewrite::RuleEliminateEvalScalar; use super::rewrite::RuleFoldCountAggregate; @@ -47,16 +49,36 @@ use crate::optimizer::rule::RuleID; use crate::optimizer::rule::RulePtr; use crate::MetadataRef; -pub struct RuleFactory; +// read only, so thread safe +pub static mut RULE_FACTORY: Lazy = Lazy::new(RuleFactory::create); + +pub struct RuleFactory { + pub transformation_rules: roaring::RoaringBitmap, + pub exploration_rules: roaring::RoaringBitmap, +} impl RuleFactory { - pub fn create_rule(id: RuleID, metadata: MetadataRef) -> Result { + pub fn create() -> Self { + RuleFactory { + transformation_rules: (RuleID::NormalizeScalarFilter as u32 + ..RuleID::CommuteJoin as u32) + .collect::(), + exploration_rules: (RuleID::CommuteJoin as u32..(RuleID::RightExchangeJoin as u32) + 1) + .collect::(), + } + } + + pub fn create_rule(&self, id: RuleID, metadata: Option) -> Result { match id { RuleID::EliminateEvalScalar => Ok(Box::new(RuleEliminateEvalScalar::new())), RuleID::PushDownFilterUnion => Ok(Box::new(RulePushDownFilterUnion::new())), RuleID::PushDownFilterEvalScalar => Ok(Box::new(RulePushDownFilterEvalScalar::new())), - RuleID::PushDownFilterJoin => Ok(Box::new(RulePushDownFilterJoin::new(metadata))), - RuleID::PushDownFilterScan => Ok(Box::new(RulePushDownFilterScan::new(metadata))), + RuleID::PushDownFilterJoin => { + Ok(Box::new(RulePushDownFilterJoin::new(metadata.unwrap()))) + } + RuleID::PushDownFilterScan => { + Ok(Box::new(RulePushDownFilterScan::new(metadata.unwrap()))) + } RuleID::PushDownFilterSort => Ok(Box::new(RulePushDownFilterSort::new())), RuleID::PushDownLimitUnion => Ok(Box::new(RulePushDownLimitUnion::new())), RuleID::PushDownLimitScan => Ok(Box::new(RulePushDownLimitScan::new())), @@ -82,7 +104,7 @@ impl RuleFactory { RuleID::LeftExchangeJoin => Ok(Box::new(RuleLeftExchangeJoin::new())), RuleID::RightExchangeJoin => Ok(Box::new(RuleRightExchangeJoin::new())), RuleID::ExchangeJoin => Ok(Box::new(RuleExchangeJoin::new())), - RuleID::PushDownPrewhere => Ok(Box::new(RulePushDownPrewhere::new(metadata))), + RuleID::PushDownPrewhere => Ok(Box::new(RulePushDownPrewhere::new(metadata.unwrap()))), } } } diff --git a/src/query/sql/src/planner/optimizer/rule/mod.rs b/src/query/sql/src/planner/optimizer/rule/mod.rs index 32d994a66737..d635716a4419 100644 --- a/src/query/sql/src/planner/optimizer/rule/mod.rs +++ b/src/query/sql/src/planner/optimizer/rule/mod.rs @@ -21,6 +21,7 @@ mod transform; mod transform_result; pub use factory::RuleFactory; +pub use factory::RULE_FACTORY; pub use rewrite::try_push_down_filter_join; pub use rule::Rule; pub use rule::RuleID; diff --git a/src/query/sql/src/planner/optimizer/rule/rule.rs b/src/query/sql/src/planner/optimizer/rule/rule.rs index 6ee65621aac1..312d97b0d316 100644 --- a/src/query/sql/src/planner/optimizer/rule/rule.rs +++ b/src/query/sql/src/planner/optimizer/rule/rule.rs @@ -16,8 +16,6 @@ use std::fmt::Display; use std::fmt::Formatter; use common_exception::Result; -use num_derive::FromPrimitive; -use num_derive::ToPrimitive; use crate::optimizer::rule::TransformResult; use crate::optimizer::SExpr; @@ -38,9 +36,10 @@ pub trait Rule { // If add a new rule, please add it to the operator's corresponding `transformation_candidate_rules` // Such as `PushDownFilterAggregate` is related to `Filter` operator. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, FromPrimitive, ToPrimitive)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum RuleID { // Rewrite rules + // Filter NormalizeScalarFilter, NormalizeDisjunctiveFilter, PushDownFilterAggregate, @@ -49,21 +48,30 @@ pub enum RuleID { PushDownFilterJoin, PushDownFilterScan, PushDownFilterSort, + EliminateFilter, + MergeFilter, + + // EvalScalar + EliminateEvalScalar, + MergeEvalScalar, + + // Limit PushDownLimitUnion, PushDownLimitOuterJoin, RulePushDownLimitExpression, PushDownLimitSort, PushDownLimitAggregate, PushDownLimitScan, - PushDownSortScan, - EliminateEvalScalar, - EliminateFilter, - MergeEvalScalar, - MergeFilter, + + // Agg SplitAggregate, FoldCountAggregate, + PushDownPrewhere, + // Sort + PushDownSortScan, + // Exploration rules CommuteJoin, RightAssociateJoin, diff --git a/src/query/sql/src/planner/optimizer/rule/rule_set.rs b/src/query/sql/src/planner/optimizer/rule/rule_set.rs index 29bcd35ad4b5..7c14908cbf1b 100644 --- a/src/query/sql/src/planner/optimizer/rule/rule_set.rs +++ b/src/query/sql/src/planner/optimizer/rule/rule_set.rs @@ -12,62 +12,65 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::collections::HashMap; +use std::collections::HashSet; use std::hash::Hash; use std::hash::Hasher; -use num_traits::FromPrimitive; -use roaring::RoaringBitmap; +use common_exception::ErrorCode; +use common_exception::Result; +// use num_traits::FromPrimitive; +use crate::optimizer::rule::factory::RuleFactory; use crate::optimizer::rule::RuleID; +use crate::optimizer::rule::RulePtr; /// Set of `Rule` -#[derive(Debug, Clone, PartialEq, Default)] pub struct RuleSet { - rules: RoaringBitmap, + rules: HashMap, } impl RuleSet { pub fn create() -> Self { RuleSet { - rules: RoaringBitmap::new(), + rules: HashMap::new(), } } - pub fn create_with_ids(ids: Vec) -> Self { + pub fn create_with_ids(ids: Vec) -> Result { + let factory = RuleFactory::create(); let mut rule_set = Self::create(); for id in ids { - rule_set.rules.insert(id as u32); + if rule_set.contains(&id) { + return Err(ErrorCode::Internal(format!("Duplicated Rule: {id}",))); + } + rule_set.insert(factory.create_rule(id, None)?); } - rule_set - } - pub fn insert(&mut self, id: RuleID) { - self.rules.insert(id as u32); + Ok(rule_set) } - pub fn contains(&self, id: &RuleID) -> bool { - self.rules.contains(*id as u32) + pub fn insert(&mut self, rule: RulePtr) { + self.rules.insert(rule.id(), rule); } - pub fn remove(&mut self, id: &RuleID) { - self.rules.remove(*id as u32); + pub fn contains(&self, id: &RuleID) -> bool { + self.rules.contains_key(id) } - pub fn intersect(&self, other: &RuleSet) -> RuleSet { - let mut rule_set = Self::create(); - rule_set.rules = self.rules.clone() & other.rules.clone(); - rule_set + pub fn iter(&self) -> impl Iterator { + self.rules.values() } - pub fn iter(&self) -> impl Iterator + '_ { - self.rules.iter().map(|v| RuleID::from_u32(v).unwrap()) + pub fn get(&self, id: &RuleID) -> Option<&RulePtr> { + self.rules.get(id) } } /// A bitmap to store information about applied rules -#[derive(Debug, Clone, PartialEq, Default)] +#[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct AppliedRules { - rules: RuleSet, + rules: HashSet, } impl AppliedRules { diff --git a/src/query/sql/src/planner/plans/aggregate.rs b/src/query/sql/src/planner/plans/aggregate.rs index 46278d948de2..6007af23847c 100644 --- a/src/query/sql/src/planner/plans/aggregate.rs +++ b/src/query/sql/src/planner/plans/aggregate.rs @@ -16,6 +16,7 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::Result; +use roaring::RoaringBitmap; use crate::optimizer::ColumnSet; use crate::optimizer::Distribution; @@ -23,6 +24,7 @@ use crate::optimizer::PhysicalProperty; use crate::optimizer::RelExpr; use crate::optimizer::RelationalProperty; use crate::optimizer::RequiredProperty; +use crate::optimizer::RuleID; use crate::optimizer::Statistics; use crate::plans::Operator; use crate::plans::RelOp; @@ -84,6 +86,13 @@ impl Operator for Aggregate { RelOp::Aggregate } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + let mut ret = RoaringBitmap::new(); + ret.push(RuleID::SplitAggregate as u32); + ret.push(RuleID::FoldCountAggregate as u32); + ret + } + fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { rel_expr.derive_physical_prop_child(0) } @@ -175,7 +184,7 @@ impl Operator for Aggregate { None }; - // Derive used columns + // Derive the used columns let mut used_columns = self.used_columns()?; used_columns.extend(input_prop.used_columns); let column_stats = input_prop.statistics.column_stats; diff --git a/src/query/sql/src/planner/plans/dummy_table_scan.rs b/src/query/sql/src/planner/plans/dummy_table_scan.rs index b96aff3d3176..773a97c34dc8 100644 --- a/src/query/sql/src/planner/plans/dummy_table_scan.rs +++ b/src/query/sql/src/planner/plans/dummy_table_scan.rs @@ -16,6 +16,7 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::Result; +use roaring::RoaringBitmap; use super::Operator; use crate::optimizer::ColumnSet; @@ -37,6 +38,14 @@ impl Operator for DummyTableScan { super::RelOp::DummyTableScan } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + RoaringBitmap::new() + } + + fn exploration_candidate_rules(&self) -> roaring::RoaringBitmap { + RoaringBitmap::new() + } + fn derive_relational_prop( &self, _rel_expr: &crate::optimizer::RelExpr, diff --git a/src/query/sql/src/planner/plans/eval_scalar.rs b/src/query/sql/src/planner/plans/eval_scalar.rs index 299495856f7f..65b55af2b512 100644 --- a/src/query/sql/src/planner/plans/eval_scalar.rs +++ b/src/query/sql/src/planner/plans/eval_scalar.rs @@ -16,12 +16,14 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::Result; +use roaring::RoaringBitmap; use crate::optimizer::ColumnSet; use crate::optimizer::PhysicalProperty; use crate::optimizer::RelExpr; use crate::optimizer::RelationalProperty; use crate::optimizer::RequiredProperty; +use crate::optimizer::RuleID; use crate::optimizer::Statistics; use crate::plans::Operator; use crate::plans::RelOp; @@ -56,6 +58,11 @@ impl Operator for EvalScalar { RelOp::EvalScalar } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + (RuleID::EliminateEvalScalar as u32..RuleID::PushDownLimitUnion as u32) + .collect::() + } + fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { rel_expr.derive_physical_prop_child(0) } diff --git a/src/query/sql/src/planner/plans/filter.rs b/src/query/sql/src/planner/plans/filter.rs index eb5cfce14f6a..0a71d71fbbcb 100644 --- a/src/query/sql/src/planner/plans/filter.rs +++ b/src/query/sql/src/planner/plans/filter.rs @@ -17,12 +17,14 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::Result; +use roaring::RoaringBitmap; use crate::optimizer::ColumnSet; use crate::optimizer::PhysicalProperty; use crate::optimizer::RelExpr; use crate::optimizer::RelationalProperty; use crate::optimizer::RequiredProperty; +use crate::optimizer::RuleID; use crate::optimizer::SelectivityEstimator; use crate::optimizer::Statistics; use crate::optimizer::MAX_SELECTIVITY; @@ -52,6 +54,11 @@ impl Operator for Filter { RelOp::Filter } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + (RuleID::NormalizeScalarFilter as u32..RuleID::EliminateEvalScalar as u32) + .collect::() + } + fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { rel_expr.derive_physical_prop_child(0) } diff --git a/src/query/sql/src/planner/plans/limit.rs b/src/query/sql/src/planner/plans/limit.rs index 3d09d0fdac70..ed3ebb4cf1b7 100644 --- a/src/query/sql/src/planner/plans/limit.rs +++ b/src/query/sql/src/planner/plans/limit.rs @@ -16,12 +16,14 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::Result; +use roaring::RoaringBitmap; use crate::optimizer::Distribution; use crate::optimizer::PhysicalProperty; use crate::optimizer::RelExpr; use crate::optimizer::RelationalProperty; use crate::optimizer::RequiredProperty; +use crate::optimizer::RuleID; use crate::optimizer::Statistics; use crate::plans::Operator; use crate::plans::RelOp; @@ -37,6 +39,11 @@ impl Operator for Limit { RelOp::Limit } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + (RuleID::PushDownLimitUnion as u32..RuleID::SplitAggregate as u32) + .collect::() + } + fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { rel_expr.derive_physical_prop_child(0) } diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 655b0ae0f8a1..e136bb6c6aff 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -17,6 +17,7 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::ErrorCode; use common_exception::Result; +use roaring::RoaringBitmap; use super::aggregate::Aggregate; use super::dummy_table_scan::DummyTableScan; @@ -32,6 +33,7 @@ use crate::optimizer::PhysicalProperty; use crate::optimizer::RelExpr; use crate::optimizer::RelationalProperty; use crate::optimizer::RequiredProperty; +use crate::optimizer::RuleID; use crate::plans::runtime_filter_source::RuntimeFilterSource; use crate::plans::Exchange; use crate::plans::Window; @@ -43,6 +45,16 @@ pub trait Operator { false } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + (RuleID::NormalizeScalarFilter as u32..RuleID::CommuteJoin as u32) + .collect::() + } + + fn exploration_candidate_rules(&self) -> roaring::RoaringBitmap { + (RuleID::CommuteJoin as u32..(RuleID::RightExchangeJoin as u32) + 1) + .collect::() + } + fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result; fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result; diff --git a/src/query/sql/src/planner/plans/scan.rs b/src/query/sql/src/planner/plans/scan.rs index 7fde68edffd3..afd5ee1a8cfd 100644 --- a/src/query/sql/src/planner/plans/scan.rs +++ b/src/query/sql/src/planner/plans/scan.rs @@ -20,6 +20,7 @@ use common_catalog::table::TableStatistics; use common_catalog::table_context::TableContext; use common_exception::Result; use itertools::Itertools; +use roaring::RoaringBitmap; use crate::optimizer::histogram_from_ndv; use crate::optimizer::ColumnSet; @@ -121,6 +122,14 @@ impl Operator for Scan { RelOp::Scan } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + RoaringBitmap::new() + } + + fn exploration_candidate_rules(&self) -> roaring::RoaringBitmap { + RoaringBitmap::new() + } + fn derive_relational_prop(&self, _rel_expr: &RelExpr) -> Result { let mut used_columns = ColumnSet::new(); if let Some(preds) = &self.push_down_predicates { diff --git a/src/query/sql/src/planner/plans/sort.rs b/src/query/sql/src/planner/plans/sort.rs index 82873ecc89b4..bc0eb21d0502 100644 --- a/src/query/sql/src/planner/plans/sort.rs +++ b/src/query/sql/src/planner/plans/sort.rs @@ -16,12 +16,14 @@ use std::sync::Arc; use common_catalog::table_context::TableContext; use common_exception::Result; +use roaring::RoaringBitmap; use crate::optimizer::Distribution; use crate::optimizer::PhysicalProperty; use crate::optimizer::RelExpr; use crate::optimizer::RelationalProperty; use crate::optimizer::RequiredProperty; +use crate::optimizer::RuleID; use crate::plans::Operator; use crate::plans::RelOp; use crate::IndexType; @@ -44,6 +46,12 @@ impl Operator for Sort { RelOp::Sort } + fn transformation_candidate_rules(&self) -> roaring::RoaringBitmap { + let mut ret = RoaringBitmap::new(); + ret.push(RuleID::PushDownSortScan as u32); + ret + } + fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { rel_expr.derive_physical_prop_child(0) }