Perf/19938 grouped flat array - #24420
Open
HairstonE wants to merge 5 commits into
Open
Conversation
…rink and release memory when empty, update explain with new bytes
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #24420 +/- ##
==========================================
+ Coverage 81.18% 81.25% +0.06%
==========================================
Files 1110 1112 +2
Lines 388906 390664 +1758
Branches 388906 390664 +1758
==========================================
+ Hits 315733 317421 +1688
- Misses 54576 54612 +36
- Partials 18597 18631 +34 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Which issue does this PR close?
(Maybe Part Of)
This implements the dynamic switching approach for
GROUP BYon single integer columns, rather than sizing from known column statistics. Improving on this with known stats will be a follow up.Rationale for this change
Grouped aggregation interns every row's key into a dense group id. For a single integer column, the current path hashes and probes a hash table once per row. When the keys fall in a small range, you don't need any of that. Direct array indexing skips the hash and the probe entirely. We already do something similar with hash joins (#19411). This brings the same idea to grouping.
It sizes the window from the first batch, falls back to the hash grouper when the range is wide or sparse, and spills out-of-window keys to an overflow map. Because of the fallback it never performs worse than the current main branch.
The main win is memory and interning cost. Dense integer groups use a third to a half the memory of the hash grouper, and isolated interning runs ~2.5–2.7× faster. There's no whole-query speedup. The operator numbers below show the gain when grouping is the bottleneck. The broad benchmarks show we didn't regress anywhere.
Benchmarks run on a Mac mini.
Isolated intern — criterion, 8192-row steady-state batch, Int64:
End-to-end
aggregation_time— 50M rows(value*7)%card, min of 5:Memory —
GroupValues::size()bytes, steady state:No regression(or at least within the range of noise) on the broad benchmark wall time measurements: h2o 10/10 (q4 engages this PR's path and is -1.5%), ClickBench 43/43 (+1.5%), external_aggr 8/8 spilling under 16 MB–512 MB pools (+0.4%).
What changes are included in this PR?
The core is a new flat grouper for single integer columns. There are three modes: Uninit, Flat, and Fallback.
It starts in Uninit. The first batch sets the window. Takes the min and max of the keys and turns that into an offset and a range. If the range is small enough, it enters Flat mode and interns by direct array indexing. Keys that land outside the window go to an overflow map instead. If the first batch shows the range is too wide or too sparse, it enters Fallback and hands everything to the existing hash grouper.
In Flat mode the window grows on demand, but only when it's helping. An occupied-slot counter checks the growth. Dense windows expand. Sparse windows overflow instead of allocating unused slots. On a partial emit, the grouper releases the dead window and the overflow it no longer needs.
Are these changes tested?
Yes. Sixteen unit tests in
flat::testscover dense-id assignment, nulls, overflow above and below the window, wide and sparse fallback,emit(First)renumbering across slots/overflow/null, equivalence with the hash implementation, density-gated growth, and dead-window plus overflow release on partial emit.For sqllogictest, the full
aggregate*.sltsuite is unchanged,aggregate_memory_spill.sltand the memory-constrained spilling fuzz test are green, andexplain_analyze.sltcarries updatedAggregateExecmetrics.I also used cargo-mutants to check that the tests are robust.
Are there any user-facing changes?
No.