Skip to content

Range partition on primitives. - #24598

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

Range partition on primitives.#24598
stuhood wants to merge 3 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 (more) vectorizable, zero-allocation implementation, bringing range re-partitioning to near-parity with hash repartitioning (10x–22x 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 for strings, decimals, dictionary arrays, and composite keys.
  • Updates BatchPartitioner and RangeExpr to delegate partition routing to RangeRouter.
  • Adds a Criterion suite.

Benchmark Comparison (8,192 Rows)

Workload Partitions main branch Speedup
range_expr_routing_i64 (Isolated Primitive Routing) 8 237.3 µs 13.6 µs 17.4x
16 286.7 µs 15.5 µs 18.5x
64 415.2 µs 20.7 µs 20.1x
512 854.6 µs 35.7 µs 24.0x
range_repartition_i64_uniform (End-to-End BatchPartitioner) 8 264.8 µs 22.8 µs 11.6x
16 313.5 µs 27.4 µs 11.4x
64 462.1 µs 38.6 µs 12.0x
512 872.0 µs 84.3 µs 10.3x
range_repartition_utf8_uniform (String Keys via RowConverter) 8 464.7 µs 205.9 µs 2.3x
64 958.4 µs 332.3 µs 2.9x
range_repartition_composite_i64 (Composite (i64, i64) Keys) 8 344.2 µs 127.5 µs 2.7x
64 545.9 µs 260.0 µs 2.1x

Are these changes tested?

Yes:

  • New tests in datafusion/physical-plan/src/repartition/range.rs covering ASC/DESC sort options, nulls_first / nulls_last, floats (with total order comparison), strings, and composite keys.
  • Criterion suite in datafusion/physical-plan/benches/range_repartition.rs.

Are there any user-facing changes?

No.

@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.93277% with 86 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.45%. Comparing base (26b40dd) to head (06849b5).
⚠️ Report is 29 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/physical-plan/src/repartition/range.rs 83.53% 45 Missing and 24 partials ⚠️
datafusion/physical-plan/src/repartition/mod.rs 70.17% 13 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24598      +/-   ##
==========================================
+ Coverage   81.43%   81.45%   +0.01%     
==========================================
  Files        1118     1120       +2     
  Lines      399414   400805    +1391     
  Branches   399414   400805    +1391     
==========================================
+ Hits       325278   326465    +1187     
- Misses      55145    55241      +96     
- Partials    18991    19099     +108     

☔ 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 on lines +1020 to +1026
let data_types: Vec<DataType> = if !split_points.is_empty() {
(0..ordering.len())
.map(|col_idx| split_points[0].values()[col_idx].data_type())
.collect()
} else {
vec![]
};

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.

Should the key types come from the ordering exprs rather than split_points[0]? RowConverter needs an exact type match where compare_rows tolerated decimal precision / timestamp tz differences.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

AFAIK, we don't have the schema here. But after planning, split_points should already be aligned with the expected schema, so that should be fine...?

@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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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