Repository navigation
Commit ea33cce
authored
feat(optimizer): logical rewrite Filter(row_number() = 1) over PARTITION BY → Aggregate(FIRST_VALUE(... ORDER BY)) (#23824)
## Which issue does this PR close?
- Closes #23603
## Rationale for this change
DF plans the common "top-1 per group" pattern (`ROW_NUMBER() OVER
(PARTITION BY ... ORDER BY ...) WHERE rn = 1`) as a full window sort
followed by a filter - this is expensive on wide payloads because it
materializes and ranks every row before discarding most.
This PR adds a logical optimizer rule that recognizes the pattern and
rewrites it to `GROUP BY` partition keys with `first_value(col ORDER BY
...)`, which can pick the winning row per group without a full sort. The
rule is gated behind `optimizer.enable_row_number_to_aggregate` and
defaults to off until nested-type `GroupsAccumulator` support lands in
#23601/#23628, since the rewritten aggregate only becomes
memory-efficient once that fast path exists.
## What changes are included in this PR?
Adds `ReplaceFilterTop1`, a new logical optimizer rule that matches
`Filter(rn = 1 | rn <= 1 | rn < 2)` over a single `row_number()` window
with a non-empty `PARTITION BY`, and rewrites it to `Projection ->
Aggregate(first_value(...) ORDER BY ...) -> child`, preserving the
filter's output schema. It supports the direct `Filter -> Window` shape
and `Filter -> Projection -> Window` when the projection passes the
row_number column through unchanged.
A new config option
`datafusion.optimizer.enable_row_number_to_aggregate` was added, and
config docs and `information_schema.slt` are updated accordingly.
## Are these changes tested?
Yes
## Are there any user-facing changes?
Yes, users can opt in with `SET
datafusion.optimizer.enable_row_number_to_aggregate = true`. The new
setting is documented in `docs/source/user-guide/configs.md` and appears
in `information_schema`1 parent 181a87a commit ea33cce
9 files changed
Lines changed: 902 additions & 0 deletions
File tree
- datafusion
- common/src
- core/src
- optimizer/src
- sqllogictest/test_files
- docs/source/user-guide
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1644 | 1644 | | |
1645 | 1645 | | |
1646 | 1646 | | |
| 1647 | + | |
| 1648 | + | |
| 1649 | + | |
| 1650 | + | |
| 1651 | + | |
| 1652 | + | |
| 1653 | + | |
| 1654 | + | |
| 1655 | + | |
| 1656 | + | |
1647 | 1657 | | |
1648 | 1658 | | |
1649 | 1659 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
53 | 54 | | |
54 | 55 | | |
55 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| 57 | + | |
57 | 58 | | |
58 | 59 | | |
59 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
52 | 53 | | |
53 | 54 | | |
54 | 55 | | |
| |||
302 | 303 | | |
303 | 304 | | |
304 | 305 | | |
| 306 | + | |
305 | 307 | | |
306 | 308 | | |
307 | 309 | | |
| |||
0 commit comments