Skip to content

Commit

Permalink
feat(planner): Eliminate unnecessary sort (#14023)
Browse files Browse the repository at this point in the history
eliminate unnecessary sort
  • Loading branch information
leiysky authored Dec 14, 2023
1 parent 1d3828d commit 61b4af4
Show file tree
Hide file tree
Showing 21 changed files with 249 additions and 2 deletions.
10 changes: 10 additions & 0 deletions src/query/sql/src/planner/optimizer/property/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::collections::HashSet;

use super::column_stat::ColumnStatSet;
use crate::plans::ScalarExpr;
use crate::plans::SortItem;
use crate::IndexType;

pub type ColumnSet = HashSet<IndexType>;
Expand Down Expand Up @@ -59,6 +60,15 @@ pub struct RelationalProperty {

/// Used columns of a relational expression
pub used_columns: ColumnSet,

/// Ordering information of a relational expression
/// The sequence of sort items is important.
/// No ordering information is ensured if empty.
///
/// TODO(leiysky): it's better to place ordering property
/// to the physical property, but at that time, we will have
/// to enforce the ordering property manually.
pub orderings: Vec<SortItem>,
}

#[derive(Default, Clone)]
Expand Down
2 changes: 2 additions & 0 deletions src/query/sql/src/planner/optimizer/rule/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use super::rewrite::RulePushDownLimitExpression;
use super::rewrite::RulePushDownPrewhere;
use super::rewrite::RuleTryApplyAggIndex;
use crate::optimizer::rule::rewrite::RuleEliminateFilter;
use crate::optimizer::rule::rewrite::RuleEliminateSort;
use crate::optimizer::rule::rewrite::RuleMergeEvalScalar;
use crate::optimizer::rule::rewrite::RuleMergeFilter;
use crate::optimizer::rule::rewrite::RuleNormalizeAggregate;
Expand Down Expand Up @@ -87,6 +88,7 @@ impl RuleFactory {
RuleID::EagerAggregation => Ok(Box::new(RuleEagerAggregation::new(metadata))),
RuleID::PushDownPrewhere => Ok(Box::new(RulePushDownPrewhere::new(metadata))),
RuleID::TryApplyAggIndex => Ok(Box::new(RuleTryApplyAggIndex::new(metadata))),
RuleID::EliminateSort => Ok(Box::new(RuleEliminateSort::new())),
}
}
}
2 changes: 2 additions & 0 deletions src/query/sql/src/planner/optimizer/rule/rewrite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod filter_join;
mod rule_commute_join;
mod rule_eliminate_eval_scalar;
mod rule_eliminate_filter;
mod rule_eliminate_sort;
mod rule_fold_count_aggregate;
mod rule_infer_filter;
mod rule_merge_eval_scalar;
Expand Down Expand Up @@ -45,6 +46,7 @@ mod rule_try_apply_agg_index;
pub use rule_commute_join::RuleCommuteJoin;
pub use rule_eliminate_eval_scalar::RuleEliminateEvalScalar;
pub use rule_eliminate_filter::RuleEliminateFilter;
pub use rule_eliminate_sort::RuleEliminateSort;
pub use rule_fold_count_aggregate::RuleFoldCountAggregate;
pub use rule_infer_filter::RuleInferFilter;
pub use rule_merge_eval_scalar::RuleMergeEvalScalar;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;

use common_exception::Result;

use crate::optimizer::rule::Rule;
use crate::optimizer::rule::RuleID;
use crate::optimizer::rule::TransformResult;
use crate::optimizer::RelExpr;
use crate::optimizer::SExpr;
use crate::plans::PatternPlan;
use crate::plans::RelOp;
use crate::plans::Sort;

pub struct RuleEliminateSort {
id: RuleID,
patterns: Vec<SExpr>,
}

impl RuleEliminateSort {
pub fn new() -> Self {
Self {
id: RuleID::EliminateSort,
// Sort
// \
// *
patterns: vec![SExpr::create_unary(
Arc::new(
PatternPlan {
plan_type: RelOp::Sort,
}
.into(),
),
Arc::new(SExpr::create_leaf(Arc::new(
PatternPlan {
plan_type: RelOp::Pattern,
}
.into(),
))),
)],
}
}
}

impl Rule for RuleEliminateSort {
fn id(&self) -> RuleID {
self.id
}

fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> {
let sort: Sort = s_expr.plan().clone().try_into()?;
let input = s_expr.child(0)?;
let rel_expr = RelExpr::with_s_expr(input);
let prop = rel_expr.derive_relational_prop()?;

if prop.orderings == sort.items {
// If the derived ordering is completely equal to
// the sort operator, we can eliminate the sort.
state.add_result(input.clone());
}

Ok(())
}

fn patterns(&self) -> &Vec<SExpr> {
&self.patterns
}
}
3 changes: 3 additions & 0 deletions src/query/sql/src/planner/optimizer/rule/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub static DEFAULT_REWRITE_RULES: LazyLock<Vec<RuleID>> = LazyLock::new(|| {
RuleID::NormalizeScalarFilter,
RuleID::NormalizeAggregate,
RuleID::EliminateFilter,
RuleID::EliminateSort,
RuleID::MergeFilter,
RuleID::InferFilter,
RuleID::MergeEvalScalar,
Expand Down Expand Up @@ -95,6 +96,7 @@ pub enum RuleID {
PushDownSortScan,
EliminateEvalScalar,
EliminateFilter,
EliminateSort,
MergeEvalScalar,
MergeFilter,
SplitAggregate,
Expand Down Expand Up @@ -128,6 +130,7 @@ impl Display for RuleID {
RuleID::PushDownSortScan => write!(f, "PushDownSortScan"),
RuleID::EliminateEvalScalar => write!(f, "EliminateEvalScalar"),
RuleID::EliminateFilter => write!(f, "EliminateFilter"),
RuleID::EliminateSort => write!(f, "EliminateSort"),
RuleID::MergeEvalScalar => write!(f, "MergeEvalScalar"),
RuleID::MergeFilter => write!(f, "MergeFilter"),
RuleID::NormalizeScalarFilter => write!(f, "NormalizeScalarFilter"),
Expand Down
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ impl Operator for Aggregate {
output_columns,
outer_columns,
used_columns,
orderings: vec![],
}))
}

Expand Down
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/constant_table_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ impl Operator for ConstantTableScan {
output_columns: self.columns.clone(),
outer_columns: Default::default(),
used_columns: self.columns.clone(),
orderings: vec![],
}))
}

Expand Down
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/cte_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ impl Operator for CteScan {
output_columns: self.used_columns()?,
outer_columns: ColumnSet::new(),
used_columns: self.used_columns()?,
orderings: vec![],
}))
}

Expand Down
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/dummy_table_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl Operator for DummyTableScan {
output_columns: ColumnSet::from([DUMMY_COLUMN_INDEX]),
outer_columns: ColumnSet::new(),
used_columns: ColumnSet::new(),
orderings: vec![],
}))
}

Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/eval_scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,14 @@ impl Operator for EvalScalar {
let mut used_columns = self.used_columns()?;
used_columns.extend(input_prop.used_columns.clone());

// Derive orderings
let orderings = input_prop.orderings.clone();

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ impl Operator for Filter {
let mut used_columns = self.used_columns()?;
used_columns.extend(input_prop.used_columns.clone());

// Derive orderings
let orderings = input_prop.orderings.clone();

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,14 @@ impl Operator for Join {
used_columns.extend(left_prop.used_columns.clone());
used_columns.extend(right_prop.used_columns.clone());

// Derive orderings
let orderings = vec![];

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
2 changes: 2 additions & 0 deletions src/query/sql/src/planner/plans/materialized_cte.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ impl Operator for MaterializedCte {
let output_columns = right_prop.output_columns.clone();
let outer_columns = right_prop.outer_columns.clone();
let used_columns = right_prop.used_columns.clone();
let orderings = right_prop.orderings.clone();

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/project_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ impl Operator for ProjectSet {
);
}

// Derive orderings
let orderings = vec![];

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ impl Operator for Scan {
output_columns: self.columns.clone(),
outer_columns: Default::default(),
used_columns: self.used_columns(),
orderings: vec![],
}))
}

Expand Down
16 changes: 15 additions & 1 deletion src/query/sql/src/planner/plans/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,21 @@ impl Operator for Sort {
}

fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result<Arc<RelationalProperty>> {
rel_expr.derive_relational_prop_child(0)
let input_prop = rel_expr.derive_relational_prop_child(0)?;

let output_columns = input_prop.output_columns.clone();
let outer_columns = input_prop.outer_columns.clone();
let used_columns = input_prop.used_columns.clone();

// Derive orderings
let orderings = self.items.clone();

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

fn derive_cardinality(&self, rel_expr: &RelExpr) -> Result<Arc<StatInfo>> {
Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/udf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,14 @@ impl Operator for Udf {
let mut used_columns = self.used_columns()?;
used_columns.extend(input_prop.used_columns.clone());

// Derive orderings
let orderings = input_prop.orderings.clone();

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/union_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,14 @@ impl Operator for UnionAll {
used_columns.extend(left_prop.used_columns.clone());
used_columns.extend(right_prop.used_columns.clone());

// Derive orderings
let orderings = vec![];

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
4 changes: 4 additions & 0 deletions src/query/sql/src/planner/plans/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,14 @@ impl Operator for Window {
let mut used_columns = self.used_columns()?;
used_columns.extend(input_prop.used_columns.clone());

// Derive orderings
let orderings = input_prop.orderings.clone();

Ok(Arc::new(RelationalProperty {
output_columns,
outer_columns,
used_columns,
orderings,
}))
}

Expand Down
Loading

0 comments on commit 61b4af4

Please sign in to comment.