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
{{ message }}
Repository navigation
Partial aggregate state reaches the final aggregate without a memory reservation (median, array_agg) #26705
For aggregates whose state holds every input value, such as median, percentile_cont and array_agg, the state moves from the partial aggregate to the final aggregate without a memory reservation. The partial aggregate emits its whole state as one batch, then its stream ends and releases its reservation. The final aggregate reserves memory only after it has merged a batch. In between, states as large as the input are held unreserved, so a plan with more than one partition uses far more memory than the pool allows.
To Reproduce
Run each query in its own datafusion-cli process (/usr/bin/time -l is macOS; use -v on Linux):
About the same as Query 1: the extra memory is the partial states, which should be reserved while held
Query 1 is above the limit for a separate reason: its value buffer reallocates into one twice its size before freeing the old one, the same shape as #25606.
One direction: the final aggregate reserves an incoming state batch before merging it, since the contract in memory_pool/mod.rs makes the operator that holds batches responsible for them.
I'm not planning to fix this myself, so anyone is welcome to pick it up. Feel free to ping me with questions about the cause or when you'd like a review.
@jayzhan211, my understanding is that the partial aggregate releases its reservation after emitting a state batch, while the final aggregate accounts for that memory only after merging it. Reproduced this with the multi-partition median and array_agg cases, then reserved incoming state before the merge and checked when that reservation can be released. If it’s still available, and the approach sounds right, I would like to work on this. Also, let me know if I've missed anything!
Activity
yashdotrv commentedon Nov 5, 2026
@jayzhan211, my understanding is that the partial aggregate releases its reservation after emitting a state batch, while the final aggregate accounts for that memory only after merging it. Reproduced this with the multi-partition median and array_agg cases, then reserved incoming state before the merge and checked when that reservation can be released. If it’s still available, and the approach sounds right, I would like to work on this. Also, let me know if I've missed anything!