Filter operator — WHERE predicate row-by-rowMySQL 8.4 • MariaDB 11.4

Understand the internal execution loop of a Filter stage: evaluate every input row, then keep or discard.

Lesson familyFilter Operator

Parameters (filter stage)

Rows entering filter: 1000000
Rows kept by WHERE: 5.0%

Example query this animation executes

SELECT order_id, total FROM orders WHERE total > 500;

EXPLAIN Filter node behavior: child operator emits rows, then this stage evaluates WHERE total > 500 row-by-row before passing rows upward.

What you'll see in the animation

  • Left stream is child output rows entering the filter stage.
  • Middle Filter operator evaluates predicate logic for every incoming row.
  • Green rows satisfy the predicate and continue to parent operators.
  • Red rows are discarded, but CPU work already happened for them.
Ready — press Play
0.0s 0.0s

Cost readout (filter operator)

Input rows ?Rows entering the filter stage from its child operator.

Output rows ?Rows that satisfy the WHERE predicate and continue upward in the plan.

Dropped rows ?Rows evaluated but rejected by the predicate.

Selectivity ?Percentage of input rows that survive the predicate.

Rows evaluated vs rows returned (log–log)

Learn more — why filter nodes still matter

A Filter node is not always bad — it is normal in many plans. The key question is how many rows arrive at this stage.

If a selective predicate is pushed down into an index access path, far fewer rows reach this filter stage.

When you see large input rows and tiny output rows, consider adding/adjusting indexes so filtering happens earlier.