GroupIdNode: Understanding Row Multiplication for Aggregations

GroupIdNode is a query execution component in Trino that enables processing multiple grouping combinations in a single pass. It’s primarily used for two purposes:

  1. Grouping sets operations (CUBE, ROLLUP, GROUPING SETS)
  2. Separating distinct and non-distinct aggregations for optimization

How GroupIdNode Works

GroupIdNode uses a technique called row multiplication - it takes each input row and creates multiple output rows, each customized for a different grouping combination.

The Process

  1. Row Multiplication: For each input row, create N copies (where N = number of grouping sets)
  2. Selective Nulling: In each copy, null out columns not part of that grouping set
  3. Group Identification: Add a groupId column to identify which grouping set each row represents

Example

Input data:

| customer | region | amount |
|----------|--------|--------|
| Alice    | US     | 100    |
| Bob      | EU     | 200    |

For the mixed aggregation case with grouping sets: ([region], [region, customer])

GroupIdNode output:

| customer | region | amount | groupId |
|----------|--------|--------|---------|
| null     | US     | 100    | 0       | ← Group 0: non-distinct context
| Alice    | US     | 100    | 1       | ← Group 1: distinct context
| null     | EU     | 200    | 0       | ← Group 0: non-distinct context  
| Bob      | EU     | 200    | 1       | ← Group 1: distinct context
  • Group 0: customer is nulled out (for non-distinct aggregations)
  • Group 1: Both customer and region are preserved (for distinct aggregations)

Use in Aggregation Optimization

GroupIdNode is also used by the PushPartialAggregationThroughExchange optimizer to separate distinct and non-distinct aggregations.

For queries like:

SELECT region, COUNT(*), COUNT(DISTINCT customer)
FROM orders GROUP BY region

GroupIdNode creates separate contexts:

  • Group 0: For non-distinct aggregations (COUNT(*))
  • Group 1: For distinct aggregations (COUNT(DISTINCT customer))

This allows the optimizer to apply different processing strategies to each aggregation type while maintaining correctness.