pub struct PushDownFilter {}Expand description
Optimizer rule for pushing (moving) filter expressions down in a plan so they are applied as early as possible.
§Introduction
The goal of this rule is to improve query performance by eliminating redundant work.
For example, given a plan that sorts all values where a > 10:
Filter (a > 10)
Sort (a, b)A better plan is to filter the data before the Sort, which sorts fewer rows and therefore does less work overall:
Sort (a, b)
Filter (a > 10) <-- Filter is moved before the sortHowever it is not always possible to push filters down. For example, given a plan that finds the top 3 values and then keeps only those that are greater than 10, if the filter is pushed below the limit it would produce a different result.
Filter (a > 10) <-- can not move this Filter before the limit
Limit (fetch=3)
Sort (a, b)More formally, a filter-commutative operation is an operation op that
satisfies filter(op(data)) = op(filter(data)).
The filter-commutative property is plan and column-specific. A filter on a
can be pushed through a Aggregate(group_by = [a], agg=[sum(b)). However, a
filter on sum(b) can not be pushed through the same aggregate.
§Handling Conjunctions
It is possible to only push down part of a filter expression if is
connected with ANDs (more formally if it is a “conjunction”).
For example, given the following plan:
Filter(a > 10 AND sum(b) < 5)
Aggregate(group_by = [a], agg = [sum(b))The a > 10 is commutative with the Aggregate but sum(b) < 5 is not.
Therefore it is possible to only push part of the expression, resulting in:
Filter(sum(b) < 5)
Aggregate(group_by = [a], agg = [sum(b))
Filter(a > 10)§Handling Column Aliases
This optimizer must sometimes handle re-writing filter expressions when they
pushed, for example if there is a projection that aliases a+1 to "b":
Filter (b > 10)
Projection: [a+1 AS "b"] <-- changes the name of `a+1` to `b`To apply the filter prior to the Projection, all references to b must be
rewritten to a+1:
Projection: a AS "b"
Filter: (a + 1 > 10) <--- changed from b to a + 1§Implementation Notes
This implementation performs a single pass through the plan, “pushing” down filters. When it passes through a filter, it stores that filter, and when it reaches a plan node that does not commute with that filter, it adds the filter to that place. When it passes through a projection, it re-writes the filter’s expression taking into account that projection.
Implementations§
Trait Implementations§
Source§impl Debug for PushDownFilter
impl Debug for PushDownFilter
Source§impl Default for PushDownFilter
impl Default for PushDownFilter
Source§fn default() -> PushDownFilter
fn default() -> PushDownFilter
Source§impl OptimizerRule for PushDownFilter
impl OptimizerRule for PushDownFilter
Source§fn apply_order(&self) -> Option<ApplyOrder>
fn apply_order(&self) -> Option<ApplyOrder>
ApplyOrder for details. Read moreSource§fn supports_rewrite(&self) -> bool
fn supports_rewrite(&self) -> bool
Source§fn rewrite(
&self,
plan: LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Transformed<LogicalPlan>>
fn rewrite( &self, plan: LogicalPlan, _config: &dyn OptimizerConfig, ) -> Result<Transformed<LogicalPlan>>
plan to an optimized form, returning Transformed::yes
if the plan was rewritten and Transformed::no if it was not.Auto Trait Implementations§
impl Freeze for PushDownFilter
impl RefUnwindSafe for PushDownFilter
impl Send for PushDownFilter
impl Sync for PushDownFilter
impl Unpin for PushDownFilter
impl UnwindSafe for PushDownFilter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more