malinjawi opened a new pull request, #12554:
URL: https://github.com/apache/gluten/pull/12554

   ## What changes were proposed in this pull request?
   
   Adds `LazyAggregateExpandRule` to the Velox backend: a post-transform rule 
that, for grouping analytics (ROLLUP / CUBE / GROUPING SETS), moves the partial 
aggregation below the Expand operator so the input is aggregated once at the 
finest grain, then expands only the intermediate aggregation buffers and merges 
them before shuffle.
   
   Before:
   
   ```
   ColumnarExchange
     HashAggregate(Partial)        <- hashes (input rows x grouping sets)
       Expand                      <- input rows x grouping sets
         child
   ```
   
   After:
   
   ```
   ColumnarExchange
     HashAggregate(PartialMerge, flushable)  <- collapses coarse-grain 
duplicates pre-shuffle
       Expand                                <- fine-grain groups x grouping 
sets (buffers only)
         HashAggregate(Partial, flushable)   <- input rows, finest grain
           child
   ```
   
   Gated by 
`spark.gluten.sql.columnar.backend.velox.lazyAggregateExpand.enabled` (default 
**false**). No native changes; the rewrite reuses existing companion-function, 
extract-struct/row-construct, and flush/abandon machinery.
   
   ## Why are the changes needed?
   
   Expand multiplies every input row by the number of grouping sets (TPC-DS 
q67: 9x on an 8-key rollup), and the partial aggregate pays hashing and shuffle 
for every copy. When the finest grain reduces the row count, aggregating first 
is substantially cheaper, and the coarser grouping sets collapse from 
already-aggregated states.
   
   Safety on high-cardinality keys (where the finest grain does not reduce): 
both inserted aggregates are flushable, so Velox's abandon-partial-aggregation 
turns the bottom aggregate into a streaming to-intermediate conversion and the 
merge stage into an identity pass-through - the worst case degrades to roughly 
the original plan plus one cheap pass. This is the failure mode that regressed 
q67 for the CH backend's lazy expand (#7986, fixed there by a native 
re-aggregation step in #7995); here the protection comes from existing Velox 
machinery.
   
   Prior art: the CH backend has this optimization since #7649 (GLUTEN-7647, 
default-on there). #12052 explored the same direction for the Velox backend; 
this PR adds the pre-shuffle merge stage, exprId-based attribute binding, the 
adaptive worst-case protection, and a dedicated test suite.
   
   ## Eligibility (v1, conservative)
   
   - `sum` / `count` / `min` / `max` / `avg`; no DISTINCT, no FILTER, no 
`try_sum`, no `bloom_filter_agg`
   - all modes Partial; grouping and shuffle keys are attributes/literals; at 
least one attribute-backed grouping key of atomic type (guards the degenerate 
`GROUPING SETS ((),())` empty-input case)
   - aggregate inputs must be pass-through columns of the Expand (this also 
auto-rejects the `RewriteDistinctAggregates` Expand); deterministic 
pre-projections and filters only
   - float `sum`/`avg` follow the same `floatingPointMode` policy as flushable 
aggregation
   - every new node passes native validation, otherwise the rule leaves the 
plan untouched
   
   ## Benchmarks (algorithm validation)
   
   SQL-level simulation of the rewrite on vanilla Spark 4.0.1 (local[10], 
12-core machine; result sets checksum-verified identical; the simulation pays 
one extra shuffle the actual rule avoids, so these numbers understate the rule):
   
   | dataset | fine-grain profile | baseline | rewrite | delta |
   |---|---|---|---|---|
   | 50M rows, 4 keys, 100k fine groups | strong reduction | 7.5s | 2.3s | 3.2x 
faster |
   | 30M rows, 8 keys, 9 sets, 3.1 rows/group (q67-shaped) | weak fine 
reduction, strong coarse collapse | 134.6s | 43.3s | 3.1x faster |
   | 20M rows, near-unique keys | no reduction | 25.0s | 47.6s | unprotected 
worst case; motivates the flushable/abandon requirement above |
   
   Gluten A/B numbers on TPC-DS (q67, q18, q22, q36, q77, q80) with the flag 
on/off will follow - keeping this as a draft until then.
   
   ## How was this patch tested?
   
   New `LazyAggregateExpandSuite` (20 cases): plan-shape assertions (flushable 
aggregates on both sides of the Expand) plus result comparison against vanilla 
Spark, covering rollup/cube with sum/count/min/max/avg, genuine-NULL keys vs 
rolled-up NULL with `grouping_id`, decimal sum buffers, the pre-projected q67 
shape, aggregates over grouping keys, empty input, degenerate grouping sets, 
duplicate grouping sets, single and multi count-distinct, FILTER / strict-float 
/ non-whitelisted-function / non-atomic-key rejections, early-abandon 
interplay, AQE on/off, and flushable-disabled behavior.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to