Skip to content

Range partition on primitives. - #24598

Open
stuhood wants to merge 5 commits into
apache:mainfrom
paradedb:stuhood.range-re-partition
Open

Range partition on primitives.#24598
stuhood wants to merge 5 commits into
apache:mainfrom
paradedb:stuhood.range-re-partition

Conversation

@stuhood

@stuhood stuhood commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

In query plans that use range re-partitioning (such as matching the range partitioning of underlying base data, or evaluating dynamic range filters in hash joins), range re-partitioning can represent a significant fraction of total query execution time.

As detailed in the issue, the existing implementation in RepartitionExec / BatchPartitioner and RangeExpr assigns rows to partitions on a row-by-row basis using extract_row_at_idx_to_buf and dynamic ScalarValue comparisons. This allocates per row and has dynamic dispatch overhead, making range re-partitioning 15x–30x slower than hash re-partitioning on standard integer keys.

This PR adds a zero-allocation, vectorizable implementation, achieving 10x–16x speedup on primitive numeric keys and 2x–3x speedup on string and composite keys.

What changes are included in this PR?

  • Adds an internal RangeRouter with specialized routing paths:
    • A zero-allocation path for single primitive numeric, temporal, and float columns that binary searches directly over Arrow buffer slices.
    • A (more) vectorizable path using Arrow's RowConverter storing flat Rows buffers for strings, decimals, dictionary arrays, and composite keys.
  • Updates RepartitionExec to construct and share an Arc<RangeRouter> across input partitions, avoiding redundant split-point encoding.
  • Updates BatchPartitioner and RangeExpr to delegate partition routing to RangeRouter.
  • Adds BatchPartitioner::try_new_range_partitioner and deprecates BatchPartitioner::new_range_partitioner.
  • Adds a Criterion suite.

Benchmark Results (vs main baseline)

Benchmark Partitions Baseline (main) This PR Speedup
range_repartition_i64_uniform 8 275.3 µs (29.8 Melem/s) 23.4 µs (349.5 Melem/s) 11.7x
64 459.8 µs (17.8 Melem/s) 40.9 µs (200.4 Melem/s) 11.2x
512 1,194.6 µs (6.86 Melem/s) 89.9 µs (91.2 Melem/s) 12.2x
range_repartition_i64_sequential 8 291.8 µs (28.1 Melem/s) 23.2 µs (353.6 Melem/s) 12.6x
64 478.6 µs (17.1 Melem/s) 38.5 µs (212.9 Melem/s) 12.4x
512 989.9 µs (8.28 Melem/s) 83.9 µs (97.6 Melem/s) 11.8x
range_repartition_utf8_uniform 8 543.5 µs (15.1 Melem/s) 184.2 µs (44.5 Melem/s) 3.0x
64 964.7 µs (8.49 Melem/s) 330.5 µs (24.8 Melem/s) 2.9x
512 1,333.2 µs (6.14 Melem/s) 551.7 µs (14.8 Melem/s) 2.4x
range_repartition_composite_i64 8 344.2 µs (23.8 Melem/s) 114.3 µs (71.7 Melem/s) 3.0x
64 516.9 µs (15.8 Melem/s) 249.7 µs (32.8 Melem/s) 2.1x
512 985.3 µs (8.31 Melem/s) 473.6 µs (17.3 Melem/s) 2.1x

Are these changes tested?

Added unit and integration tests.

Are there any user-facing changes?

  • Added BatchPartitioner::try_new_range_partitioner(&RangePartitioning, Time) -> Result<Self>.
  • Deprecated BatchPartitioner::new_range_partitioner in favor of fallible try_new_range_partitioner.

@github-actions github-actions Bot added the physical-plan Changes to the physical-plan crate label Aug 23, 2026
@codecov-commenter

codecov-commenter commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.90743% with 129 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.57%. Comparing base (a274959) to head (612381c).

Files with missing lines Patch % Lines
datafusion/physical-plan/src/repartition/range.rs 84.21% 57 Missing and 30 partials ⚠️
datafusion/physical-plan/src/repartition/mod.rs 74.07% 32 Missing and 10 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24598      +/-   ##
==========================================
- Coverage   81.58%   81.57%   -0.01%     
==========================================
  Files        1123     1124       +1     
  Lines      406610   407237     +627     
  Branches   406610   407237     +627     
==========================================
+ Hits       331719   332206     +487     
- Misses      55453    55552      +99     
- Partials    19438    19479      +41     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@stuhood
stuhood force-pushed the stuhood.range-re-partition branch from 5579f93 to a6a8368 Compare August 23, 2026 22:40
@stuhood
stuhood marked this pull request as ready for review August 23, 2026 22:40
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
@Dandandan

Copy link
Copy Markdown
Contributor

Nice results!
I think two easy further optimizations could be using extend and perhaps further optimizing the rowconverter path.
Ok to postpone it to a follow-up PR however you like!

@Dandandan Dandandan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 efficiency comments

Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some optimization things and linear scan path that might be interesting 👍

Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/mod.rs
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs
Comment thread datafusion/physical-plan/src/repartition/mod.rs
@gene-bordegaray

Copy link
Copy Markdown
Contributor

here are my samplys:

You will see the cachine RowConverter gets rid of the drop_glue::RowConverter then the partition_grouped_take takes over as dominant

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Aug 24, 2026
@stuhood
stuhood force-pushed the stuhood.range-re-partition branch from 6f4a2df to ccaab13 Compare August 24, 2026 20:58

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think there is some strctural things that could be improved with responsiblities. I prposed a rough idea. Let me know what you think @stuhood

Comment thread datafusion/physical-plan/src/repartition/mod.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs
Comment thread datafusion/physical-plan/src/repartition/mod.rs Outdated
@stuhood
stuhood force-pushed the stuhood.range-re-partition branch from d87522a to 06849b5 Compare August 26, 2026 19:26
@github-actions github-actions Bot removed the auto detected api change Auto detected API change label Aug 26, 2026

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

starting to get there. I think this is last major round of comments

Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs
Comment thread datafusion/physical-plan/src/repartition/range.rs
Comment thread datafusion/physical-plan/src/repartition/range.rs
Comment thread datafusion/physical-plan/src/repartition/mod.rs Outdated
Comment thread datafusion/physical-plan/src/repartition/range.rs Outdated
Comment thread datafusion/physical-plan/benches/range_repartition.rs
Comment thread datafusion/physical-plan/src/repartition/mod.rs Outdated

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops did not mean to approve

@stuhood
stuhood force-pushed the stuhood.range-re-partition branch from 06849b5 to f387d6d Compare August 31, 2026 20:13
@stuhood
stuhood force-pushed the stuhood.range-re-partition branch from f387d6d to 612381c Compare August 31, 2026 20:16
@stuhood

stuhood commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Split out the benchmarks into the bottom commit, and applied review feedback in the top commit.

The initial benchmark results were a bit optimistic (they never regressed during review feedback: they were just a bit off when they were initially posted). Now updated.

Thanks for the feedback!

@github-actions

Copy link
Copy Markdown

Thank you for opening this pull request!

Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch).

Details
     Cloning apache/main
    Building datafusion-physical-plan v55.0.0 (current)
       Built [  41.251s] (current)
     Parsing datafusion-physical-plan v55.0.0 (current)
      Parsed [   0.130s] (current)
    Building datafusion-physical-plan v55.0.0 (baseline)
       Built [  33.886s] (baseline)
     Parsing datafusion-physical-plan v55.0.0 (baseline)
      Parsed [   0.127s] (baseline)
    Checking datafusion-physical-plan v55.0.0 -> v55.0.0 (no change; assume patch)
     Checked [   0.879s] 223 checks: 222 pass, 1 fail, 0 warn, 31 skip

--- failure type_method_marked_deprecated: type method #[deprecated] added ---

Description:
A type method is now #[deprecated]. Downstream crates will get a compiler warning when using this method.
        ref: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/type_method_marked_deprecated.ron

Failed in:
  method datafusion_physical_plan::repartition::BatchPartitioner::new_range_partitioner in /home/runner/work/datafusion/datafusion/datafusion/physical-plan/src/repartition/mod.rs:1013

     Summary semver requires new minor version: 0 major and 1 minor checks failed
    Finished [  77.791s] datafusion-physical-plan

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Aug 31, 2026
@stuhood

stuhood commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

A type method is now #[deprecated]. Downstream crates will get a compiler warning when using this method.

Hm... is this not allowed for commits landing on main? Or is this not a blocking comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto detected api change Auto detected API change physical-plan Changes to the physical-plan crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve the performance of range re-partitioning

6 participants