datafusion_optimizer::push_down_filter

Struct PushDownFilter

Source
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 sort

However 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§

Source§

impl PushDownFilter

Source

pub fn new() -> Self

Trait Implementations§

Source§

impl Debug for PushDownFilter

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for PushDownFilter

Source§

fn default() -> PushDownFilter

Returns the “default value” for a type. Read more
Source§

impl OptimizerRule for PushDownFilter

Source§

fn name(&self) -> &str

A human readable name for this optimizer rule
Source§

fn apply_order(&self) -> Option<ApplyOrder>

How should the rule be applied by the optimizer? See comments on ApplyOrder for details. Read more
Source§

fn supports_rewrite(&self) -> bool

Does this rule support rewriting owned plans (rather than by reference)?
Source§

fn rewrite( &self, plan: LogicalPlan, _config: &dyn OptimizerConfig, ) -> Result<Transformed<LogicalPlan>>

Try to rewrite plan to an optimized form, returning Transformed::yes if the plan was rewritten and Transformed::no if it was not. Read more
Source§

fn try_optimize( &self, _plan: &LogicalPlan, _config: &dyn OptimizerConfig, ) -> Result<Option<LogicalPlan>>

👎Deprecated since 40.0.0: please implement supports_rewrite and rewrite instead
Try and rewrite plan to an optimized form, returning None if the plan cannot be optimized by this rule. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,