You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Range([key, timestamp]) with a lex split (k2, 01:00) is not the same as Range([timestamp]).
Partition 0: rows < (k2, 01:00), including (k1, 02:00)
Partition 1: rows >= (k2, 01:00)
The same date_bin(timestamp) can appear on both sides if key is not in the GROUP BY. Example: (k1, 02:00) and (k2, 02:00) share hour 02:00 but sit in different partitions.
GROUP BY (key, date_bin(timestamp))is partition-disjoint on that layout: key is the lex prefix, and an aligned date_bin is disjoint on the timestamp component of the split. GROUP BY date_bin(timestamp) alone is not.
Proposed rule
A group-key set G is partition-disjoint for a multi-key range only if no group can appear on both sides of every lex split.
For each split, either:
the full lex prefix of the range key is in G, and the remaining key has a disjoint monotonic transform in G, or
the first differing range key has a disjoint monotonic transform in G.
Compound split-point “predecessor” is not “predecessor of column i only.” Adjacent partitions are defined by the full lex compare.
RangePartitioning::project can already rewrite Range([key, timestamp]) → Range([key, time_bin]) when the projection keeps key and date_bin(timestamp). That only preserves output metadata. It does not skip the shuffle. Satisfaction is the missing piece.
Describe the solution you'd like
Implement the lex-prefix + disjoint-transform check in range_monotonic_fn_satisfies_keys (or a dedicated helper).
Tests:
Range([key, timestamp]) + GROUP BY (key, date_bin(aligned)) → satisfied (no shuffle).
Range([key, timestamp]) + GROUP BY date_bin(...) only → not satisfied.
Unaligned / straddling bin (e.g. date_trunc('day') or date_bin(70 minutes) on an hour split) → not satisfied.
Optional SLT table that declares compound range metadata (today’s listing fixtures are single-key).
Is your feature request related to a problem?
Child of epic #22395 and leftover work from #23569 / #24501.
#23569 asked that both of these layouts skip a hash shuffle for
Range([timestamp])with splits aligned to the bin — done in feat: skip hash shuffle for date_bin/date_trunc on Range([timestamp]) #24501. Extra GROUP BY keys (a, …) are a superset of the transformed range key, sorange_monotonic_fn_satisfies_keyscan use.any().Rangeontimestampanda(compound / multi-key range) — not done.#24501 fail-closes on compound range:
A unit test asserts
Range([key, timestamp])does not satisfyGROUP BY (key, date_bin(timestamp))via that path.Jayant asked on #24501 whether this expands in a follow-up:
#24501 (comment)
Why this is not “drop the
len() != 1check”Range([key, timestamp])with a lex split(k2, 01:00)is not the same asRange([timestamp]).< (k2, 01:00), including(k1, 02:00)>= (k2, 01:00)The same
date_bin(timestamp)can appear on both sides ifkeyis not in the GROUP BY. Example:(k1, 02:00)and(k2, 02:00)share hour02:00but sit in different partitions.So this is unsafe:
GROUP BY (key, date_bin(timestamp))is partition-disjoint on that layout:keyis the lex prefix, and an aligneddate_binis disjoint on the timestamp component of the split.GROUP BY date_bin(timestamp)alone is not.Proposed rule
A group-key set
Gis partition-disjoint for a multi-key range only if no group can appear on both sides of every lex split.For each split, either:
G, and the remaining key has a disjoint monotonic transform inG, orG.Compound split-point “predecessor” is not “predecessor of column
ionly.” Adjacent partitions are defined by the full lex compare.RangePartitioning::projectcan already rewriteRange([key, timestamp])→Range([key, time_bin])when the projection keepskeyanddate_bin(timestamp). That only preserves output metadata. It does not skip the shuffle. Satisfaction is the missing piece.Describe the solution you'd like
range_monotonic_fn_satisfies_keys(or a dedicated helper).Range([key, timestamp])+GROUP BY (key, date_bin(aligned))→ satisfied (no shuffle).Range([key, timestamp])+GROUP BY date_bin(...)only → not satisfied.date_trunc('day')ordate_bin(70 minutes)on an hour split) → not satisfied.Describe alternatives you've considered
len() != 1guard forever. Fine if nobody declaresRange([key, timestamp]). Support functions date_bin and date_trunc in range partition satisfaction #23569 still lists case (2).GROUP BY date_binonly on a compound range.Additional context