Blog post about TopK per partition (`PartitionedTopKExec` / `enable_window_topn`)
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
- 難度
- 3/5
- 預估耗時
- 1-2 天
- 新手友好度
- 72/100
- Issue 類型
- 文件
- 描述清晰度
- 描述清楚
- 活躍度
- 活躍
研究方向
Start with the draft in this issue and the linked DataFusion site pull request #203; use the referenced TopK per partition issues and pull requests to check behavior, implementation details, and whether the optimization is enabled by default for the target release. Write a self-contained post for the DataFusion blog using the suggested outline, examples, and related posts for style. Done means a site PR explains the use case, how the operator works and is used, implementation highlights, and remaining work.
由索引模型根據 Issue 內容生成。
描述
Is your feature request related to a problem or challenge?
There is a lot of great work from @SubhamSinghal, @jayzhan211 and others on the "TopK per partition" optimization for window queries like
SELECT * FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY category ORDER BY revenue DESC) AS rn, *
FROM sales
) WHERE rn <= 5;
The original request is from 2023:
The optimization landed in DataFusion 55 behind datafusion.optimizer.enable_window_topn, and the EPIC to turn it on by default is
As always, telling the community about it will be good
- To advertise the feature for others who have the same use case,
- To document in an easier to understand way how the feature works
- The authors to raise their visibility.
I had drafted a section about it for the DataFusion 55 release post (see below) but a release post isn't great as it has limited space to explain how the operator works
- https://github.com/apache/datafusion/issues/24216
- https://github.com/apache/datafusion-site/pull/203
Describe the solution you'd like
Thus I suggest a complete self contained blog post on https://datafusion.apache.org/blog/ (make a PR to https://github.com/apache/datafusion-site) about TopK per partition.
I suggest the standard structure of "informative post with low key DataFusion pitch"
For example, the pattern of
- Dynamic Filters (TopK and hash join, 25x faster): https://datafusion.apache.org/blog/2025/09/10/dynamic-filters/
- Fast high cardinality grouping: https://datafusion.apache.org/blog/2023/08/05/datafusion_fast_grouping/
Here are some ideas for an outline:
- An understandable representative usecase: "top N per group" (e.g latest N events per device) so readers can tell if it applies to them. Mention this is db-benchmark / h2o query 8 shape.
- Background / technical intuition: the naive plan sorts the entire input to compute the window function and then throws almost all of it away. The TopK per partition operator keeps a bounded heap per partition instead. Explain how
ROW_NUMBER,RANKandDENSE_RANKdiffer in what has to be retained. - How to use it in DataFusion: What version is it introduced in (57 I hope, show
EXPLAINbefore/after withPartitionedTopKExec), and how to turn it off) - A bit about how it is implemented: the
WindowTopNphysical optimizer rule,PartitionedTopKExec, and then some of the highlights of making it work for high cardinality:- the 100K+ partition cliff, https://github.com/apache/datafusion/pull/21479#issuecomment-4221809099
- Memory optimizations, etc
- Emitting the rank column directly from the operator so the window node can be removed (#26133)
- Call for help 🎣: Any remaining work that needs to happen
I think the best time to publish is around 57 release (when #27197 is merged and released, so the post can say the optimization is on by default.
Describe alternatives you've considered
Here is the original text I had drafted for the 55 release post (from https://github.com/apache/datafusion/issues/24608), which could be a starting point:
Details
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
Additional context
Tracking issues:
- https://github.com/apache/datafusion/issues/6899 (original 2023 request)
- https://github.com/apache/datafusion/issues/24608 (enable by default EPIC)
- https://github.com/apache/datafusion/issues/24060 (follow on optimizations)
- https://github.com/apache/datafusion/issues/23197 (window function performance EPIC)
Core operator and optimizer rule:
- https://github.com/apache/datafusion/pull/21479 (
ROW_NUMBER, @SubhamSinghal) - https://github.com/apache/datafusion/pull/22885 (
RANK, @SubhamSinghal) - https://github.com/apache/datafusion/pull/23869 (
DENSE_RANK, @SubhamSinghal) - https://github.com/apache/datafusion/pull/24191 (run
WindowTopNbeforeEnforceRequirements, @saadtajwar) - https://github.com/apache/datafusion/pull/23355 (range partitioned inputs, @stuhood)
- https://github.com/apache/datafusion/pull/26133 (emit the rank column from the operator, @SubhamSinghal)
- https://github.com/apache/datafusion/pull/27197 (enable by default, @SubhamSinghal)
Closing the high cardinality gap:
- https://github.com/apache/datafusion/pull/23096 (share encoder and reservation across partitions)
- https://github.com/apache/datafusion/pull/24591 (
RANKmemory from O(input) to O(K + ties), @jayzhan211) - https://github.com/apache/datafusion/pull/25468 (interleave retained rows at emit)
- https://github.com/apache/datafusion/pull/25730 (shared
RecordBatchStoreforROW_NUMBER) - https://github.com/apache/datafusion/pull/25968 (
RANKon the shared store with decide-then-gather)
Correctness fixes and metrics:
- https://github.com/apache/datafusion/pull/24405 (@viirya)
- https://github.com/apache/datafusion/pull/23599 (@zhuqi-lucas)
- https://github.com/apache/datafusion/pull/24495 (metrics, @shinzoxD)
- https://github.com/apache/datafusion/pull/26417 (filter column through projections)
- https://github.com/apache/datafusion/pull/25535 (@jayzhan211)
Benchmarks:
- https://github.com/apache/datafusion/pull/24050 (
dense_rankbenchmark) - https://github.com/apache/datafusion/pull/24732 (h2o
window_sortedsweep)
Open follow on work:
- https://github.com/apache/datafusion/issues/26381 (
Utf8Viewbuffers kept alive) - https://github.com/apache/datafusion/issues/26876 / https://github.com/apache/datafusion/pull/27136 (
DENSE_RANKon the shared store) - https://github.com/apache/datafusion/issues/21596 (filters with embedded projections)
- https://github.com/apache/datafusion/pull/26160 (
rn = 1) - https://github.com/apache/datafusion/issues/23600 (
ROW_NUMBER() = 1/DISTINCT ONdedup) - https://github.com/apache/datafusion/pull/24629 (streaming path for pre-sorted input, closed but a good idea)
Related prior posts for style / context:
- 主要語言
- Rust
- 星號
- 9.6k
- 分支
- 2.6k
- 平均合併
- 3 天 4 小時
- 30 天內合併 PR
- 345
環境準備
在瀏覽器裡用你自己的 GitHub 帳號啟動這個專案的開發容器。
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
apache/datafusion 的其他 Issue
-
難度 2/5 1-3 小時 新手友好度 72/100
apache/datafusion#27315 · 2 則留言 ·
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 76/100
apache/datafusion#27094 · 1 則留言 ·
維護者通常 1 天內回覆
-
Substrait consumer doesn't recognise `shift_left` / `shift_right` from functions_arithmetic.yaml可能已有人在做 @jonasHanhan 於 9 天前認領。 未關閉bug
難度 2/5 1-3 小時 新手友好度 76/100
apache/datafusion#27059 ·
維護者通常 1 天內回覆
-
`ProjectionExprs::project_statistics` computes approximate `Statistics::total_byte_size` ignoring column stats可能已有人在做 @joseph-isaacs 於 10 天前認領。 未關閉bug
難度 2/5 1-3 小時 新手友好度 72/100
apache/datafusion#27050 ·
維護者通常 1 天內回覆
-
physical-plan: decoding an Unnest or Explain node with an unset field panics可能已有人在做 @geoHeil 於 9 天前認領。 未關閉
難度 2/5 1-3 小時 新手友好度 75/100
apache/datafusion#26999 · 1 則留言 ·
維護者通常 1 天內回覆
查看 apache/datafusion 的全部 Issue
相似的 Issue
-
P3
難度 2/5 1-3 小時 新手友好度 70/100
HerringtonDarkholme/hd-lang#1770 ·
維護者通常 1 天內回覆
-
needs triage
難度 2/5 1-3 小時 新手友好度 85/100
pbakaus/impeccable#1436 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 82/100
jonathanong/no-mistakes#3332 ·
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 78/100
swc-project/swc-next-issues#310 ·
-
bug
難度 2/5 1-3 小時 新手友好度 72/100
swc-project/swc-ai-issues#653 ·