Skip to content

Enable TopK per Partition (datafusion.optimizer.enable_window_topn) by default #24608

Description

@alamb

Is your feature request related to a problem or challenge?

While writing the DataFusion 55.0.0 blog post

I wrote up the per-partition TopK window optimization as one of the headline performance improvements of the release — and only then discovered that datafusion.optimizer.enable_window_topn defaults to false, so nobody actually gets it unless they opt in.

We probably shouldn't make a big deal about a feature that is off by default, and I could not find any issue tracking turning it on. So I am filing this issue so we don't forget and we can track what is required to do so in one place rather than scattered across PR review threads.

The story we want to be able to tell

This is the text I had drafted for the 55.0.0 blog post before pulling it, included so it's clear what we're aiming for and so whoever finishes this work can reuse it:

Per-Partition TopK for Window Functions

A common analytics pattern selects the top N rows per group using a window
function:

SELECT * FROM (
    SELECT ROW_NUMBER() OVER (PARTITION BY category ORDER BY revenue DESC) AS rn, *
    FROM sales
) WHERE rn <= 5;

DataFusion previously sorted the entire input to evaluate the window
function, even though only a handful of rows per partition survive the filter.
DataFusion 55 recognizes this pattern and uses a new PartitionedTopKExec
operator that keeps only the top N rows per partition, dramatically reducing
sorting and memory for high-cardinality inputs. The optimization applies to
ROW_NUMBER and RANK, resolving a feature request first filed in 2023
(#6899).
Thanks to @SubhamSinghal for implementing this feature, with reviews from
@2010YOUY01 and @kosiew. Related PRs: #21479, #22885, #23096

Why it is currently off

datafusion/common/src/config.rs:

/// When set to true, the optimizer will replace
/// Filter(rn<=K) → Window(ROW_NUMBER) → Sort patterns with a
/// PartitionedTopKExec that maintains per-partition heaps, avoiding
/// a full sort of the input.
/// When the window partition key has low cardinality, enabling this optimization
/// can improve performance. However, for high cardinality keys, it may
/// cause regressions in both memory usage and runtime.
pub enable_window_topn: bool, default = false

The default was set to false in #21479 because of severe high-cardinality regressions against the plain-sort baseline:

If it has regressions as large as 0.03x it should [be] off by default (and
we should look if we can automatically enable it via a heuristic / stats based
on partition cardinality / rows)
@Dandandan, #21479 (comment)

#23096 (in 55.0.0) closed most of that gap by sharing the encoder and memory
reservation across partitions:

Partitions main with #23096 vs sort baseline
100 110 ms 105 ms ~1.0x
1,000 117 ms 110 ms ~1.0x
10,000 640 ms 137 ms 1.7x faster than sort (was a regression)
100,000 4,327 ms 320 ms 320 ms vs 238 ms — still slower

but explicitly did not flip the default:

enable_window_topn default stays false per the #21479 discussion — 100K+
remains slower than sort on average, so this PR doesn't motivate flipping the
default. It's the prerequisite for further optimizations that would attack the
residual 100K+ cliff.
#23096

Describe the solution you'd like

Set enable_window_topn to true by default, once we are confident it does not
regress. Known work items:

Describe alternatives you've considered

Leave it opt-in indefinitely. 👎 -- an optimization nobody turns on is close to an optimization that doesn't exist

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    EPICA larger project, actively underway, with sub tasksenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions