Repository navigation
EPIC: complete GroupValuesColumn type coverage (nested types + remaining primitives) #22715
Description
Background
GroupValuesColumn (the column-wise multi-column GROUP BY storage) provides type-specific specializations under multi_group_by/ so a wide GROUP BY can use the column-native + short-circuit fast path instead of falling back to the byte-encoded GroupValuesRows path. Today the type allow-list is partial: any column outside the supported set drags the entire grouping onto the slow path, even when every other column would have qualified for the fast one.
This EPIC tracks completing the GroupValuesColumn type coverage so that the row-encoded fallback is needed only as an explicit opt-in, not as a forced fallback for missing specializations.
Already supported (today on main)
Int8..Int64, UInt8..UInt64, Float32, Float64, Decimal128, Utf8, LargeUtf8, Utf8View, Binary, LargeBinary, BinaryView, Boolean, Date32, Date64, Time32(Second/Millisecond), Time64(Microsecond/Nanosecond)†, Timestamp(*).
† Time64 alignment between supported_type and the dispatcher is being fixed as part of PR #22706.
Tracking
Nested types
- feat: add GroupColumn support for List / Struct / Map / FixedSizeList in multi-column GROUP BY #22682 —
FixedSizeList<primitive>,List<T>,LargeList<T>,Struct<...>with recursive children. In flight via PR feat(physical-plan): add GroupColumn support for FixedSizeList / List / LargeList / Struct in multi-column GROUP BY #22706 (split into 5 stacked PRs per maintainer request).
Remaining primitives
Each item below blocks on the make_group_column factory and recursive supported_type landing in PR 1 of the #22706 sequence. After that, each is an independently mergeable PR.
-
FixedSizeBinary. Fixed-width bytes per row. Closest in shape toPrimitiveGroupValueBuilderbut with a runtime-known fixed byte width. Likely the smallest new builder. In progress via PR Add FixedSizeBinary support for MultiGroupBy #23646. -
Float16. Arrow already has the primitive type; need explicit NaN handling inis_eq(match the Float32 / Float64 behavior inPrimitiveGroupValueBuilder). Done via PR feat: add GroupColumn support for Float16 in multi-column GROUP BY #23785. -
Duration(TimeUnit). Same shape asTimestamp(fourTimeUnitarms in the dispatcher), fourDurationXxxTypeslot-ins. Done via PR feat: add GroupColumn support for Duration in multi-column GROUP BY #23783. -
Interval(IntervalUnit). Three variants (YearMonth = 4 bytes, DayTime = 8 bytes, MonthDayNano = 16 bytes), three separate dispatcher arms and three native widths. Done via PR feat: add GroupColumn support for Interval in multi-column GROUP BY #23786. -
Decimal256.arrow::array::types::Decimal256TypehasNative = arrow_buffer::i256, a 32-byte struct rather than aCopy-cheap native scalar. Either relax theT: Copyrequirement inPrimitiveGroupValueBuilderor add a sibling builder specialized to wide native types. Done via PR feat: add GroupColumn support for Decimal256 in multi-column GROUP BY #23849. -
Dictionary<K, V>. Most involved. Specialize GroupColumn storage for Dictionary and Run-End Encoded group keys #23993 Need to decide:- Option A: hash / compare on the dictionary's decoded logical value. Conceptually clean, behaves like
Utf8/Binary. Costlier in memory because each unique decoded value is materialized at intern time. - Option B: hash / compare on the encoded key under a fixed-dictionary contract (i.e. the same
K -> Vmapping is asserted across batches). Cheaper but only safe if the dictionary is shared / known-stable, which is not guaranteed by Arrow at the schema level.
- Option A: hash / compare on the dictionary's decoded logical value. Conceptually clean, behaves like
Related strategic direction (not blocked by this EPIC)
#22701 proposes a generic FallbackGroupColumn so any Arrow type can go through GroupValuesColumn with a type-erased Arrow comparator. If that lands, the items in this EPIC become opt-in fast-path specializations on top of the generic fallback rather than prerequisites for the column-wise path. The two directions are complementary.
Cross-cutting requirements
Every new builder added under this EPIC should follow the testing structure established by PR #22706:
- append / build round trip
equal_tofor identical / different / null edgestake_nboundary cases (n=0,n=len, with-null prefix)- sliced input array (offset != 0)
vectorized_*matches per-row referencesize()grows with appendsbuildon empty builder- Entry in the
supported_type↔make_group_columnconsistency fuzz - Entry in the dhat-based memory regression harness (being added in PR 1 of feat(physical-plan): add GroupColumn support for FixedSizeList / List / LargeList / Struct in multi-column GROUP BY #22706 per review)
Activity
[-]EPIC: fill out remaining primitive GroupColumn implementations (FixedSizeBinary / Float16 / Duration / Interval / Decimal256 / Dictionary)[/-][+]EPIC: complete GroupValuesColumn type coverage (nested types + remaining primitives)[/+]refactor(physical-plan): extract make_group_column factory + tighten …
refactor(physical-plan): extract make_group_column factory + tighten …
refactor(physical-plan): extract make_group_column factory + tighten …
refactor(physical-plan): extract make_group_column factory + tighten …
refactor(physical-plan): extract make_group_column factory + tighten …
refactor(physical-plan): extract make_group_column factory + tighten …
refactor(physical-plan): extract make_group_column factory + eager in…
refactor(physical-plan): extract make_group_column factory + eager in…
alamb commentedon Jun 22, 2026
BTW once you have implemented all f these, it would be great to change the code from "fallback if not implemented" to "don't compile if not implemented"
feat(physical-plan): add GroupColumn support for FixedSizeList<primit…
Address Rich-T-kid review on apache#23128: assert! + comment tightening
feat(physical-plan): add GroupColumn support for Duration in multi-co…
feat(physical-plan): add generic Rows-backed GroupColumn to keep mixe…
11 remaining items
alamb commentedon Aug 8, 2026
Now that we merged the support for Decimal
Shall we claim this issue is complete?
zhuqi-lucas commentedon Aug 8, 2026
The List/Struct/ etc (nested type) support for GroupValuesColumn still not merged, but we can track as follow-up, for example :
#23648
alamb commentedon Aug 10, 2026
I updated the list "Remaining primitives" in the description with the various PRs we have up to fix it.
The last remaining primitive is fixedsizebinary from @maxburke : #23646
I am trying to review that one now
So what do you think about creating a follow on epic just for the nested types, and closing this one down with the primitive types being complete?
I think a nice "definition of done" for the new epic would be "remove
GroupValuesRows" (as that would ensure we never fallzhuqi-lucas commentedon Aug 11, 2026
Thanks @alamb sounds good — let's close this one once #23646 (FixedSizeBinary) lands, and we can open a follow-up EPIC for the nested types with "remove GroupValuesRows" as the definition of done.
alamb commentedon Aug 11, 2026
I filed this as the new epic to track and have put #23646 in the merge queue
GroupValuesColumnfor Faster Aggregation support #24268Thanks @zhuqi-lucas
zhuqi-lucas commentedon Aug 11, 2026
Thanks @alamb , close this epic now.
Add FixedSizeBinary support for MultiGroupBy (apache#23646)
feat(physical-plan): generic Rows-backed GroupColumn keeps mixed sche…
feat: add GroupColumn support for Duration in multi-column GROUP BY (a…
feat: add GroupColumn support for Float16 in multi-column GROUP BY (a…
feat: add GroupColumn support for Interval in multi-column GROUP BY (a…
feat: add GroupColumn support for Decimal256 in multi-column GROUP BY (…
Add FixedSizeBinary support for MultiGroupBy (apache#23646)
Add FixedSizeBinary support for MultiGroupBy (apache#23646)