You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Exact DISTINCT aggregation currently derives most of its parallelism from ownership of the final GROUP BY key. This works well when there are enough balanced groups, but it does not provide robust parallelism when the final group cardinality is small or skewed.
Examples:
SELECTCOUNT(DISTINCT user_id) FROM events;
SELECT region_id, COUNT(DISTINCT user_id)
FROM events
GROUP BY region_id;
In the first query there is only one final group. In the second query, a few regions or one hot region can own most rows. Hashing only by region_id therefore limits useful aggregate parallelism to the number and balance of regions, regardless of DOP. Increasing DOP alone cannot remove that bottleneck.
The current exact argument state also uses an ordered per-group skiplist. Admission requires key encoding, comparisons, pointer traversal, and retained-key storage. Partial-state merging can add another pass over those keys. These costs grow with DISTINCT NDV even when the final number of groups remains small.
The optimization in #27693 improves the balanced, many-group path by assigning each complete group to one owner and avoiding an expensive downstream exact-state merge. This issue covers the complementary execution shapes that cannot obtain enough parallelism from the final group key alone.
Required invariant
Exact DISTINCT work must be distributable by the identity being deduplicated, not only by the final aggregate group:
canonical key = (active GROUP BY keys, DISTINCT arguments)
Every equal canonical key must reach exactly one final deduplication owner, while different keys—even within one hot aggregate group—may be processed concurrently. Final aggregate results must remain bit-for-bit equivalent to the existing exact semantics.
Proposed execution model
Introduce an adaptive partition-parallel path for mergeable exact DISTINCT aggregates:
Project and encode the canonical (group keys, DISTINCT arguments) key once per input row or vector batch.
Compute its stable hash once and carry/reuse it across local admission, exchange, and final partitioning.
Partition surviving keys by the canonical-key hash, rather than only by the final group key.
Finalize partitions concurrently; each partition performs exact deduplication independently.
Feed unique (group keys, DISTINCT arguments) rows into the ordinary final aggregate by group key.
The implementation should reuse existing pipeline, shuffle, hash-table, and spill ownership primitives where their contracts fit. A new framework is justified only if those contracts cannot express independently owned DISTINCT partitions with lower total complexity.
Adaptive path selection
No single topology is optimal for every data shape. Planning and/or bounded runtime sampling should select among:
Small input or low NDV: keep the simple local path and avoid partition machinery.
One/few groups or high group skew: partition by (group keys, DISTINCT arguments) to expose key-level parallelism.
High duplicate ratio: deduplicate locally before exchange to reduce CPU and network bytes.
Nearly all keys unique: avoid repeated local hash probes that cannot remove meaningful input; append/partition directly and deduplicate during partition finalization.
Selection must be based on general cardinality, skew, memory, and ownership estimates—not query text, benchmark names, fixed schemas, or issue-specific constants. Missing or unreliable statistics require a conservative fallback.
Correctness and ownership requirements
The design document must be reviewed before implementation and define:
canonical equality and hashing for fixed/variable-width values, multiple DISTINCT arguments, NULL, constants, decimals, collations, floating signed zero/NaN behavior, and hash collisions;
applicability to COUNT(DISTINCT) and the explicit boundary for other DISTINCT aggregates;
sharing of one deduplication pipeline by aggregates with identical DISTINCT arguments and compatible filters;
behavior with aggregate filters, grouping sets, empty input, one/multiple CNs, DOP=1, cancellation, errors, Reset/Free, and operator reuse;
ownership and lifecycle of local tables, partition buffers, exchange batches, final tables, and any spill state;
Local pre-deduplication must reduce exchanged rows/bytes when duplicates are common and avoid material overhead when keys are nearly unique.
Common fixed-width keys should use a compact vectorized/hash-table path; an ordered skiplist should not remain mandatory when aggregate semantics require only equality.
CPU, allocations, peak accounted memory, exchanged rows/bytes, and partition skew must be measured before and after. Wall-clock time alone is insufficient.
Validation matrix
Cover independent dimensions rather than one benchmark-shaped case:
Correctness tests must compare with an independent exact oracle and include deliberate hash collisions. Plan-shape assertions may supplement but cannot replace result assertions.
Unit tests must use small deterministic data and injected thresholds. Do not add sleeps, large-data UTs, or timing-only assertions. Put larger scaling and performance measurements in a dedicated benchmark/integration job.
Acceptance criteria
Exact results match the independent oracle across the full validation matrix.
A global or single-hot-group high-NDV case demonstrates real multi-worker partition finalization and meaningful speedup over DOP=1 on the same hardware.
Motivation
Exact DISTINCT aggregation currently derives most of its parallelism from ownership of the final
GROUP BYkey. This works well when there are enough balanced groups, but it does not provide robust parallelism when the final group cardinality is small or skewed.Examples:
In the first query there is only one final group. In the second query, a few regions or one hot region can own most rows. Hashing only by
region_idtherefore limits useful aggregate parallelism to the number and balance of regions, regardless of DOP. Increasing DOP alone cannot remove that bottleneck.The current exact argument state also uses an ordered per-group skiplist. Admission requires key encoding, comparisons, pointer traversal, and retained-key storage. Partial-state merging can add another pass over those keys. These costs grow with DISTINCT NDV even when the final number of groups remains small.
The optimization in #27693 improves the balanced, many-group path by assigning each complete group to one owner and avoiding an expensive downstream exact-state merge. This issue covers the complementary execution shapes that cannot obtain enough parallelism from the final group key alone.
Required invariant
Exact DISTINCT work must be distributable by the identity being deduplicated, not only by the final aggregate group:
Every equal canonical key must reach exactly one final deduplication owner, while different keys—even within one hot aggregate group—may be processed concurrently. Final aggregate results must remain bit-for-bit equivalent to the existing exact semantics.
Proposed execution model
Introduce an adaptive partition-parallel path for mergeable exact DISTINCT aggregates:
(group keys, DISTINCT arguments)key once per input row or vector batch.(group keys, DISTINCT arguments)rows into the ordinary final aggregate by group key.The implementation should reuse existing pipeline, shuffle, hash-table, and spill ownership primitives where their contracts fit. A new framework is justified only if those contracts cannot express independently owned DISTINCT partitions with lower total complexity.
Adaptive path selection
No single topology is optimal for every data shape. Planning and/or bounded runtime sampling should select among:
(group keys, DISTINCT arguments)to expose key-level parallelism.Selection must be based on general cardinality, skew, memory, and ownership estimates—not query text, benchmark names, fixed schemas, or issue-specific constants. Missing or unreliable statistics require a conservative fallback.
Correctness and ownership requirements
The design document must be reviewed before implementation and define:
COUNT(DISTINCT)and the explicit boundary for other DISTINCT aggregates;Performance requirements
COUNT(DISTINCT)must use multiple workers when DOP > 1.Validation matrix
Cover independent dimensions rather than one benchmark-shaped case:
Correctness tests must compare with an independent exact oracle and include deliberate hash collisions. Plan-shape assertions may supplement but cannot replace result assertions.
Unit tests must use small deterministic data and injected thresholds. Do not add sleeps, large-data UTs, or timing-only assertions. Put larger scaling and performance measurements in a dedicated benchmark/integration job.
Acceptance criteria
Related