zml1206 opened a new pull request, #57815:
URL: https://github.com/apache/spark/pull/57815

   
   ### What changes were proposed in this pull request?
   This PR adds support for distinct aggregate window functions whose lower 
frame bound is
   `UNBOUNDED PRECEDING`, including:
   
   - Full-partition frames ending at `UNBOUNDED FOLLOWING`.
   - Growing `ROWS` and `RANGE` frames.
   - General distinct aggregate functions, not only `COUNT(DISTINCT ...)`.
   - Multiple distinct arguments, aggregate filters, and order-sensitive 
aggregates such as
     `LISTAGG(DISTINCT ...)`.
   
   The implementation:
   
   - Uses `BytesToBytesMap` to deduplicate binary-stable keys in memory.
   - Permanently falls back to `UnsafeKVExternalSorter` when the hash threshold 
is reached or
     memory allocation fails.
   - Uses first-occurrence events to incrementally update growing window frames.
   - Evaluates full-partition frames once without retaining or restoring the 
input row order.
   - Adds caller-owned sorter lifecycle support and spill metrics.
   - Introduces the internal
     `spark.sql.windowExec.distinct.hash.fallbackThreshold` configuration.
   
   Bounded and sliding distinct window frames remain unsupported.
   
   ### Why are the changes needed?
   Spark currently rejects all distinct aggregate window functions, including 
common expressions
   such as:
   
   ```sql
   COUNT(DISTINCT value) OVER (
     PARTITION BY key
     ORDER BY id
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
   ```
   A simple in-memory hash set can consume unbounded memory for partitions with 
many distinct
   values. This implementation combines hash-based deduplication with an 
external-sort fallback,
   providing fast execution for normal workloads while allowing large 
partitions to spill to disk.
   
   
   ### Does this PR introduce _any_ user-facing change?
   Yes.
   Users can now execute distinct aggregate window functions when the lower 
frame bound is
   UNBOUNDED PRECEDING.
   Distinct window functions with bounded lower frames, such as sliding 
windows, continue to
   produce the existing DISTINCT_WINDOW_FUNCTION_UNSUPPORTED analysis error.
   Python UDAFs and distinct inputs without a supported ordering remain 
unsupported.
   
   
   ### How was this patch tested?
   The test coverage includes:
   Growing ROWS and RANGE frames.
   Full-partition frames.
   COUNT, SUM, AVG, COLLECT_LIST, and LISTAGG with DISTINCT.
   Multiple distinct arguments, filters, and null values.
   Hash fallback triggered by entry-count and memory thresholds.
   External sorter spills and spill metric reporting.
   Binary-unstable collations, normalized floating-point values, and empty 
distinct keys.
   Negative tests for unsupported bounded frames.
   The relevant targeted SQL window tests and scalastyle checks pass locally. 
The LISTAGG
   SQL golden results were regenerated to cover the newly supported behavior.
   
   
   ### Was this patch authored or co-authored using generative AI tooling?
   Generated-by: OpenAI Codex (GPT-5)
   


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