[fix](agg) Fix grouping function handling and repeatSlotIdList calculation in DecomposeRepeatWithPreAggregation#60091
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
TPC-H: Total hot run time: 31857 ms |
TPC-DS: Total hot run time: 174145 ms |
ClickBench: Total hot run time: 26.84 s |
FE UT Coverage ReportIncrement line coverage |
FE Regression Coverage ReportIncrement line coverage |
ae3ef77 to
43a9454
Compare
|
run buildall |
TPC-H: Total hot run time: 30728 ms |
TPC-DS: Total hot run time: 173968 ms |
ClickBench: Total hot run time: 26.83 s |
FE Regression Coverage ReportIncrement line coverage |
|
run buildall |
1 similar comment
|
run buildall |
FE UT Coverage ReportIncrement line coverage |
TPC-H: Total hot run time: 30939 ms |
TPC-DS: Total hot run time: 173439 ms |
ClickBench: Total hot run time: 27.16 s |
|
run cloud_p0 |
FE Regression Coverage ReportIncrement line coverage |
1 similar comment
FE Regression Coverage ReportIncrement line coverage |
|
run buildall |
TPC-H: Total hot run time: 32310 ms |
ClickBench: Total hot run time: 28.57 s |
|
run p0 |
|
run cloud_p0 |
|
run feut |
|
run p0 |
|
run buildall |
TPC-H: Total hot run time: 30443 ms |
TPC-DS: Total hot run time: 190819 ms |
ClickBench: Total hot run time: 28.31 s |
|
run buildall |
TPC-H: Total hot run time: 30928 ms |
ClickBench: Total hot run time: 28.37 s |
FE UT Coverage ReportIncrement line coverage |
|
run buildall |
TPC-H: Total hot run time: 30167 ms |
ClickBench: Total hot run time: 28.32 s |
FE UT Coverage ReportIncrement line coverage |
FE Regression Coverage ReportIncrement line coverage |
|
PR approved by at least one committer and no changes requested. |
|
PR approved by anyone and no changes requested. |
…ation in DecomposeRepeatWithPreAggregation (apache#60091) Related PR: apache#59116 apache#60045 **Problem Summary:** There are 2 problems: 1. When `DecomposeRepeatWithPreAggregation` optimization removes the maximum grouping set, grouping functions (e.g., `grouping()`, `grouping_id()`) that reference expressions only existing in the removed grouping set would fail because of index lookup failure: When computing grouping function values, `GroupingSetShapes.indexOf()` would return -1 for expressions not in `flattenGroupingSetExpression`, causing incorrect behavior. Example scenario: ```sql SELECT a, b, c, grouping(c) FROM t1 GROUP BY GROUPING SETS ((a, b, c), (a, b), (a), ()); ``` After optimization removes the maximum grouping set `(a, b, c)`, the expression `c` no longer exists in the remaining grouping sets. When computing `grouping(c)`, the index lookup would fail. 2. The `repeatSlotIdList` calculation was incorrect because it relied on the assumption that the order of `physicalRepeat.getOutputExpressions()` matches the order of `outputTuple`. However, this assumption can be broken during rule rewriting (e.g., in `DecomposeRepeatWithPreAggregation.constructRepeat()` at line 502-503, where `replacedRepeatOutputs` is constructed by `new ArrayList<>(child.getOutput())` and then appends grouping functions, potentially changing the order). This mismatch causes incorrect slot ID mapping and wrong query results. Example scenario: When `DecomposeRepeatWithPreAggregation` rewrites a repeat plan, the output expressions order may differ from the output tuple order, leading to incorrect slot ID mapping in `repeatSlotIdList`. **Solution:** 1. For problem 1: Modified `Repeat.toShapes()` method to ensure all expressions referenced by grouping functions are included in `flattenGroupingSetExpression`, even if they are not in any grouping set. For expressions that only exist in the removed maximum grouping set, they are correctly marked as `shouldBeErasedToNull = true` in all remaining grouping sets, which is the correct SQL semantics. Key changes: - `Repeat.toShapes()`: Enhanced to collect all expressions referenced by grouping functions using `ExpressionUtils.collectToList()` and merge them into `flattenGroupingSetExpression` - For expressions not in any grouping set, they are correctly marked as `shouldBeErasedToNull = true` in all `GroupingSetShape` instances - This ensures `GroupingSetShapes.indexOf()` always returns a valid index for grouping function arguments, preventing index lookup failures 2. For problem 2: Modified `Repeat.computeRepeatSlotIdList()` method to accept an additional `outputSlots` parameter. Instead of relying on the order of `outputExpressions` matching `outputTuple`, the method now uses `outputSlots` to correctly map grouping set expressions to their indices in the output tuple. This ensures correct slot ID calculation even when rule rewriting changes the order of output expressions. Key changes: - `computeRepeatSlotIdList(List<Integer> slotIdList, List<Slot> outputSlots)`: Added `outputSlots` parameter - `getGroupingSetsIndexesInOutput(List<Slot> outputSlots)`: Modified to use `outputSlots` instead of `getOutputExpressions()` - `indexesOfOutput(List<Slot> outputSlots)`: Modified to build index map from `outputSlots` instead of `getOutputExpressions()` - `PhysicalPlanTranslator.visitPhysicalRepeat()`: Updated to pass `outputSlots` to `computeRepeatSlotIdList()` 3. Another task for this pull request is to set the shuffle key for the rewritten bottom aggregation. Choosing a suitable shuffle key can improve the aggregation rate of the top aggregation's local aggregation.
…ation in DecomposeRepeatWithPreAggregation (apache#60091) Related PR: apache#59116 apache#60045 **Problem Summary:** There are 2 problems: 1. When `DecomposeRepeatWithPreAggregation` optimization removes the maximum grouping set, grouping functions (e.g., `grouping()`, `grouping_id()`) that reference expressions only existing in the removed grouping set would fail because of index lookup failure: When computing grouping function values, `GroupingSetShapes.indexOf()` would return -1 for expressions not in `flattenGroupingSetExpression`, causing incorrect behavior. Example scenario: ```sql SELECT a, b, c, grouping(c) FROM t1 GROUP BY GROUPING SETS ((a, b, c), (a, b), (a), ()); ``` After optimization removes the maximum grouping set `(a, b, c)`, the expression `c` no longer exists in the remaining grouping sets. When computing `grouping(c)`, the index lookup would fail. 2. The `repeatSlotIdList` calculation was incorrect because it relied on the assumption that the order of `physicalRepeat.getOutputExpressions()` matches the order of `outputTuple`. However, this assumption can be broken during rule rewriting (e.g., in `DecomposeRepeatWithPreAggregation.constructRepeat()` at line 502-503, where `replacedRepeatOutputs` is constructed by `new ArrayList<>(child.getOutput())` and then appends grouping functions, potentially changing the order). This mismatch causes incorrect slot ID mapping and wrong query results. Example scenario: When `DecomposeRepeatWithPreAggregation` rewrites a repeat plan, the output expressions order may differ from the output tuple order, leading to incorrect slot ID mapping in `repeatSlotIdList`. **Solution:** 1. For problem 1: Modified `Repeat.toShapes()` method to ensure all expressions referenced by grouping functions are included in `flattenGroupingSetExpression`, even if they are not in any grouping set. For expressions that only exist in the removed maximum grouping set, they are correctly marked as `shouldBeErasedToNull = true` in all remaining grouping sets, which is the correct SQL semantics. Key changes: - `Repeat.toShapes()`: Enhanced to collect all expressions referenced by grouping functions using `ExpressionUtils.collectToList()` and merge them into `flattenGroupingSetExpression` - For expressions not in any grouping set, they are correctly marked as `shouldBeErasedToNull = true` in all `GroupingSetShape` instances - This ensures `GroupingSetShapes.indexOf()` always returns a valid index for grouping function arguments, preventing index lookup failures 2. For problem 2: Modified `Repeat.computeRepeatSlotIdList()` method to accept an additional `outputSlots` parameter. Instead of relying on the order of `outputExpressions` matching `outputTuple`, the method now uses `outputSlots` to correctly map grouping set expressions to their indices in the output tuple. This ensures correct slot ID calculation even when rule rewriting changes the order of output expressions. Key changes: - `computeRepeatSlotIdList(List<Integer> slotIdList, List<Slot> outputSlots)`: Added `outputSlots` parameter - `getGroupingSetsIndexesInOutput(List<Slot> outputSlots)`: Modified to use `outputSlots` instead of `getOutputExpressions()` - `indexesOfOutput(List<Slot> outputSlots)`: Modified to build index map from `outputSlots` instead of `getOutputExpressions()` - `PhysicalPlanTranslator.visitPhysicalRepeat()`: Updated to pass `outputSlots` to `computeRepeatSlotIdList()` 3. Another task for this pull request is to set the shuffle key for the rewritten bottom aggregation. Choosing a suitable shuffle key can improve the aggregation rate of the top aggregation's local aggregation.
What problem does this PR solve?
Related PR: #59116 #60045
Problem Summary:
There are 2 problems:
DecomposeRepeatWithPreAggregationoptimization removes the maximum grouping set, grouping functions (e.g.,grouping(),grouping_id()) that reference expressions only existing in the removed grouping set would fail because of index lookup failure: When computing grouping function values,GroupingSetShapes.indexOf()would return -1 for expressions not inflattenGroupingSetExpression, causing incorrect behavior.Example scenario:
After optimization removes the maximum grouping set
(a, b, c), the expressioncno longer exists in the remaining grouping sets. When computinggrouping(c), the index lookup would fail.2. The
repeatSlotIdListcalculation was incorrect because it relied on the assumption that the order ofphysicalRepeat.getOutputExpressions()matches the order ofoutputTuple. However, this assumption can be broken during rule rewriting (e.g., inDecomposeRepeatWithPreAggregation.constructRepeat()at line 502-503, wherereplacedRepeatOutputsis constructed bynew ArrayList<>(child.getOutput())and then appends grouping functions, potentially changing the order). This mismatch causes incorrect slot ID mapping and wrong query results.Example scenario:
When
DecomposeRepeatWithPreAggregationrewrites a repeat plan, the output expressions order may differ from the output tuple order, leading to incorrect slot ID mapping inrepeatSlotIdList.Solution:
Repeat.toShapes()method to ensure all expressions referenced by grouping functions are included inflattenGroupingSetExpression, even if they are not in any grouping set. For expressions that only exist in the removed maximum grouping set, they are correctly marked asshouldBeErasedToNull = truein all remaining grouping sets, which is the correct SQL semantics.Key changes:
Repeat.toShapes(): Enhanced to collect all expressions referenced by grouping functions usingExpressionUtils.collectToList()and merge them intoflattenGroupingSetExpressionshouldBeErasedToNull = truein allGroupingSetShapeinstancesGroupingSetShapes.indexOf()always returns a valid index for grouping function arguments, preventing index lookup failuresRepeat.computeRepeatSlotIdList()method to accept an additionaloutputSlotsparameter. Instead of relying on the order ofoutputExpressionsmatchingoutputTuple, the method now usesoutputSlotsto correctly map grouping set expressions to their indices in the output tuple. This ensures correct slot ID calculation even when rule rewriting changes the order of output expressions.Key changes:
computeRepeatSlotIdList(List<Integer> slotIdList, List<Slot> outputSlots): AddedoutputSlotsparametergetGroupingSetsIndexesInOutput(List<Slot> outputSlots): Modified to useoutputSlotsinstead ofgetOutputExpressions()indexesOfOutput(List<Slot> outputSlots): Modified to build index map fromoutputSlotsinstead ofgetOutputExpressions()PhysicalPlanTranslator.visitPhysicalRepeat(): Updated to passoutputSlotstocomputeRepeatSlotIdList()Release note
None
Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)