Skip to content

[PERF] Selective predicate selection doesn't reach equi+non-equi combined joins #1664

Description

@samukweku

Background

Found while adversarially reviewing #1663 (the fix for #1659, range-join le_lt/ge_gt selection).

_helpers._separate_conditions_based_on_op produces mapping["le_lt"]/["ge_gt"]/["le_or_ge"], consumed by two different dispatch trees:

Confirmed empirically (during #1663's review): a query combining grp ==, a > lo, and two <-type candidates with real, measured selectivity skew dispatches through _equi_range_join._get_indices with le_lt still bound to the unswapped, less-selective candidate.

Why this matters

This isn't a new inconsistency - _equi_not_range_join.py's gap predates #1658 and #1663 just didn't close the equi-adjacent copies either, for the same reason (each fix was scoped to the non-equi dispatch tree it touched). But it means none of #1657/#1658/#1659/#1663's fixes actually apply once an == predicate is combined with the inequality/range predicates - and an id/category equality plus a date/numeric range is a very ordinary join shape, arguably more common than a pure non-equi join in practice. The underlying pathology is the same one #1641/#1658/#1659 already measured (up to ~77x for same-direction, ~7-11x for range joins, worse again under join_algorithm="regions") - it just isn't fixed for this dispatch tree yet.

Correctness

Same invariance argument as #1641/#1658/#1659 applies unchanged: _equi_range_join.py/_equi_uniq_join.py still process ge_gt before le_lt structurally regardless of which candidate occupies either slot, so picking independently per bound (or per same-direction anchor) can't produce wrong output here either - this is a missed-optimization gap, not a latent correctness risk.

Ask

Extend selectivity-aware selection to the _get_indices_equi.py dispatch tree:

Both fixes already exist and are algorithm-agnostic at the point they're called (after null-stripping, before dispatch) - this should mostly be a matter of calling them from _get_indices_equi.py's own null-stripping point too, not new selection logic.

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions