yashmayya opened a new pull request, #19325:
URL: https://github.com/apache/pinot/pull/19325

   `UNION ALL` is a pure concatenation, so any row-to-worker mapping produces 
the same result. The V2 physical optimizer has always known this — 
`TraitAssignment#assignSetOp` returns early for `Union.all` ("UNION ALL means 
we can return duplicates, so no trait required"), so it never constrains the 
distribution of a union's inputs. The V1 (default) planner did not: 
`PinotSetOpExchangeNodeInsertRule` unconditionally hash-shuffled every set-op 
input on the full output row, `UNION ALL` included.
   
   This brings V1 in line with V2. When no `is_colocated_by_set_op_keys` hint 
is present, `UNION ALL` input exchanges now default to pre-partitioned (direct, 
1-to-1) sends.
   
   ### What it buys
   
   Once the exchange is marked pre-partitioned, the existing machinery does the 
rest:
   
   - `WorkerManager#isPrePartitionAssignment` lets the union stage inherit its 
leaf stages' workers, which keeps the stages above it aligned as well — the 
main win for plans with many colocated stages.
   - `MailboxAssignmentVisitor#computeDirectExchange` wires sender worker *i* 
to receiver worker *i*. When both land on the same server they share an 
in-memory mailbox, so there is no network hop and no block serialization.
   - `HashExchange#route` short-circuits when there is a single destination 
mailbox, so even the per-row hashing disappears (the plan still reads 
`HASH_DISTRIBUTED`).
   
   ### Why it cannot mis-wire a plan
   
   Correctness does not depend on placement here, and a direct exchange is only 
formed when the shapes line up: `isPrePartitionAssignment` and 
`isDirectExchangeCompatible` both require equal worker counts and matching 
partition functions across branches. When they do not match (say inputs 
partitioned 2 ways and 4 ways), the planner falls back to today's shuffle, so 
the worst case is a missed optimization rather than a bad plan. There is a 
runtime test for that fallback.
   
   Opt out per query with `/*+ 
setOpOptions(is_colocated_by_set_op_keys='false') */`.
   
   ### Set operation output distribution
   
   `PinotRelDistributionTraitRule` had no `SetOp` case, so every set operation 
fell through to `RANDOM_DISTRIBUTED`. It now derives the output distribution 
from what the input exchanges actually do:
   
   - every input genuinely shuffles (`INTERSECT` / `EXCEPT` / distinct `UNION`, 
or `UNION ALL` with the hint set to `'false'`) → hash distributed on all output 
columns, which lets a downstream exchange keyed on those columns skip its own 
shuffle;
   - any input pre-partitioned → no distribution claimed, because the mailbox 
layer may still fall back to a real shuffle.
   
   ### Two latent bug fixes
   
   Both were already reachable before this change via an explicit 
`is_colocated_by_set_op_keys='true'` hint over fully-pruned inputs. The new 
default makes them reachable without a hint, so they are fixed here:
   
   - `MailboxAssignmentVisitor#isDirectExchangeCompatible` divided by zero when 
a leaf stage had all of its segments pruned (0 senders and 0 receivers pass the 
multiplication check).
   - `WorkerManager#isPrePartitionAssignment` let a zero-worker child anchor 
the local-exchange assignment, because `partitionCount == 0` conflated "unset" 
with "computed zero". A `UNION ALL` with one branch fully pruned would then 
leave the union stage with no workers and silently return empty results.
   
   ### Notes
   
   - V1 only. The V2 physical optimizer (`usePhysicalOptimizer=true`) already 
plans `UNION ALL` without a shuffle and is untouched.
   - This changes the default plan shape for hint-free `UNION ALL` queries. 
Because the union stage now inherits its inputs' worker layout instead of 
redistributing, input skew is carried into the union stage rather than 
rebalanced; in practice the next exchange above the union re-partitions.
   - Not wire-incompatible: pre-partitioned exchanges are decided broker-side 
at plan time, so there is no rolling-upgrade concern and no `backward-incompat` 
label.
   
   ### Testing
   
   - `QueryCompilationTest` — pre-partitioned by default, the hint opt-out, 
distinct set operations unaffected, and both directions of the new distribution 
derivation.
   - `ExplainPhysicalPlans.json` — the new default plan shape, with the 
previous shuffled plan retained under the hint.
   - `QueryHints.json` (compared against H2, replayed on both optimizers) — 
`UNION ALL` correctness, dedup and `GROUP BY` above a pre-partitioned union, 
and the mismatched-partition-count fallback.
   - `MailboxAssignmentVisitorTest` / `WorkerManagerTest` — regression tests 
for the two fixes above.
   


-- 
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