Skip to content

refactor: Split hash aggregation logic into separated streams#22729

Open
2010YOUY01 wants to merge 1 commit into
apache:mainfrom
2010YOUY01:split-aggr-refactor-only
Open

refactor: Split hash aggregation logic into separated streams#22729
2010YOUY01 wants to merge 1 commit into
apache:mainfrom
2010YOUY01:split-aggr-refactor-only

Conversation

@2010YOUY01
Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

See issues.

This PR split out partial and final aggregate strem from GroupsHashAggregateStream

To fully migrate hash aggregation, we have to

Todo in this PR:

  • Add a temporary configuration enable_migration_aggregate to turn off this path

Since it should be a regression if the above features are not added, it also helps if to prevent potential regressions from the migration of other aggregate streams.

What changes are included in this PR?

Split out the streams from GroupsHashAggregateStream

  1. Partial stage of hash aggregation
  2. Final stage of hash aggregation

Are these changes tested?

Are there any user-facing changes?

@github-actions github-actions Bot added the physical-plan Changes to the physical-plan crate label Jun 3, 2026
impl Stream for PartialFinalHashAggregateStream {
type Item = Result<RecordBatch>;

fn poll_next(
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.

The state machines are identical for now, but in follow-up work, such as skipping partial aggregation for high-cardinality inputs, their control flows will diverge. I think separating them improves clarity, as discussed in #22710.

Some duplication is inevitable, but that is the trade-off.

@2010YOUY01
Copy link
Copy Markdown
Contributor Author

cc @Dandandan @ariel-miculas @alamb, who have expressed interest before.

@ariel-miculas
Copy link
Copy Markdown
Contributor

I'm curious about the high-level vision: is the plan to close #15591 in favor of this new approach?

I would like the redesign of hash aggregation to take into account the memory constraints imposed by the finite memory pool, i.e. how does the implementation perform under OOM conditions.

Otherwise we'll end up with the same issues that exist now. E.g. EmitTo::First(n) wasn't designed for emitting a large portion of the existing groups, so it over-allocated when used for emitting early in partial aggregation OOM case.

@2010YOUY01
Copy link
Copy Markdown
Contributor Author

I'm curious about the high-level vision: is the plan to close #15591 in favor of this new approach?

Yes, the goal is to support blocked state management.

The existing challenge is that the current implementation is hard to extend and review. I want to clean things up through this refactor first, and then apply the actual change.

I would like the redesign of hash aggregation to take into account the memory constraints imposed by the finite memory pool, i.e. how does the implementation perform under OOM conditions.

Otherwise we'll end up with the same issues that exist now. E.g. EmitTo::First(n) wasn't designed for emitting a large portion of the existing groups, so it over-allocated when used for emitting early in partial aggregation OOM case.

All of these issues are symptoms of managing state in a large contiguous Vec. Blocked memory allocation should address them naturally.

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.

2 participants