Skip to content

bench: pwmj left semi/anti join - #24160

Merged
kumarUjjawal merged 4 commits into
apache:mainfrom
SubhamSinghal:bench-pwmj
Aug 15, 2026
Merged

bench: pwmj left semi/anti join#24160
kumarUjjawal merged 4 commits into
apache:mainfrom
SubhamSinghal:bench-pwmj

Conversation

@SubhamSinghal

@SubhamSinghalSubhamSinghal commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Which issue does this close?

Benchmark companion to #23870 (LeftSemi / LeftAnti support for
PiecewiseMergeJoinExec), part of EPIC #17427. Closes no issue on its own.

Rationale for this change

#23870 routes existence subqueries with an inequality correlation (WHERE EXISTS (SELECT 1 FROM rhs WHERE lhs.key < rhs.key)) to PiecewiseMergeJoinExec instead of NestedLoopJoinExec. That claim needs a benchmark that can be run on either side of the change, so this PR adds the benchmark separately from the operator work — it is bench code only, no functional change.

What changes are included in this PR?

datafusion/core/benches/pwmj_semi_anti_sql.rs (+ its Cargo.toml entry), a Criterion benchmark with two arms over 20k × 20k Int32 rows, target_partitions=1:

  • pwmj_enabled — flag on
  • nlj — flag off, which can only plan NestedLoopJoinExec

Axes: join type (EXISTS → Semi, NOT EXISTS → Anti) × match regime (all_match 100%, no_match 0%, half_match ~50%, so the buffered side is only partially marked and scan depth varies per streamed row).

Are these changes tested?

Are there any user-facing changes?

No. Benchmark code only.

@github-actionsgithub-actionsBot added sqllogictest SQL Logic Tests (.slt) physical-plan Changes to the physical-plan crate labels Aug 7, 2026
@github-actionsgithub-actionsBot removed the sqllogictest SQL Logic Tests (.slt) label Aug 7, 2026
@codecov-commenter

codecov-commenter commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.05%. Comparing base (e64e3f7) to head (cdd33d9).
⚠️ Report is 77 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #24160 +/- ##
==========================================
+ Coverage 81.02% 81.05% +0.02% 
==========================================
Files 1106 1106 Lines 380718 382025 +1307 Branches 380718 382025 +1307 ==========================================
+ Hits 308489 309651 +1162 - Misses 54001 54091 +90 - Partials 18228 18283 +55 

☔ 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.

@SubhamSinghal

Copy link
Copy Markdown
ContributorAuthor

@kumarUjjawal build successful. PTAL

BenchmarkId::new(format!("pwmj_{jt}_{regime}"), right_rows),
|b| {
b.iter(|| {
let (left, right) = build_inputs();

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.

build_inputs() is timed, including generating 40,000 values and allocating arrays and batches. This can dominate the ~0.5 ms PWMJ result. Could we prebuild the batches and use iter_batched for fresh plans outside the timed section?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

resolved in d52523e

// Selectivity is set by how far the right key range sits above the left range.
// - "high": right keys mostly above left keys -> most left rows match (Semi large)
// - "low": right keys mostly below left keys -> few left rows match (Anti large)
let regimes: [(&str, i32); 2] = [("sel_high", key_span), ("sel_low", -key_span)];

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.

These offsets produce exactly all-match and no-match cases, not “mostly” and “few.” Could we label them as all/none and add an overlapping-range case to measure partial suffix marking?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

resolved in d52523e

Arc::new(Column::new("key", 0)),
);
Arc::new(
PiecewiseMergeJoinExec::try_new(

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.

Could we benchmark this through the SQL/physical planner instead of constructing PiecewiseMergeJoinExec directly? The current benchmark will panics on because existence joins are unsupported until #23870.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

addressed in d52523e

@github-actionsgithub-actionsBot added core Core DataFusion crate and removed physical-plan Changes to the physical-plan crate labels Aug 7, 2026

@kumarUjjawalkumarUjjawal 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.

Hi @SubhamSinghal Thanks for iterating.

This became a little tricky that's why we had to do more follow up. If you have any ideas you can share as-well.

] {
let ctx = create_context(right_offset, pwmj, &s);
let name = format!("{arm}_{label}_{regime}");
assert_plan_contains(

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.

This still panics on this PR’s current head because enabling PWMJ selects NestedLoopJoinExec until #23870, while this assertion requires PiecewiseMergeJoin. To use this revision as the pre-change benchmark baseline, could we name this arm pwmj_enabled and accept either NLJ or PWMJ, while keeping the disabled arm pinned to NLJ? #23870’s tests can assert that the enabled plan switches to PWMJ.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

addressed in cdd33d9

@SubhamSinghal

Copy link
Copy Markdown
ContributorAuthor

@comphead this is benchmark PR

@kumarUjjawalkumarUjjawal 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.

Looks good 👍

@compheadcomphead 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.

Thanks @SubhamSinghal for the PR.
Please update the PR description accordingly

@SubhamSinghal

Copy link
Copy Markdown
ContributorAuthor

@comphead updated PR description

@SubhamSinghal

Copy link
Copy Markdown
ContributorAuthor

@kumarUjjawal@comphead can we merge this PR?

@kumarUjjawal

Copy link
Copy Markdown
Contributor

Thank you @SubhamSinghal and @comphead

@kumarUjjawal
kumarUjjawal added this pull request to the merge queueAug 15, 2026
Merged via the queue into apache:main with commit 4403c5dAug 15, 2026
39 checks passed
@SubhamSinghal
SubhamSinghal deleted the bench-pwmj branch August 15, 2026 14:26
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

coreCore DataFusion crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@SubhamSinghal@codecov-commenter@kumarUjjawal@comphead