Skip to content

feat: support col reference for percentiles - #25337

Open
dd-annarose wants to merge 7 commits into
apache:mainfrom
dd-annarose:annarose/approx_percentile
Open

dd-annarose wants to merge 7 commits into
apache:mainfrom
dd-annarose:annarose/approx_percentile

Conversation

@dd-annarose

@dd-annarose dd-annarose commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

When using a projection as the percentile argument to approx_percentile_cont or percentile_cont, planning fails because only literals are supported.

It makes sense to accept projections that are constant across all batches but not labelled as literals (although they practically are).

For example, this query cannot be planned, even though the percentile is constant:

SELECT
    approx_percentile_cont(y, m) AS median
FROM (
    SELECT t.x + 1 as y, 0.5 as m
    FROM (
        VALUES (10)
    ) AS t(x)
)

What changes are included in this PR?

Introduce PercentileParam and PercentileParamState to handle column references or projections for the percentile argument.

Resolution of percentile cannot always be done: for example, on an empty record batch, we won't be able to get the value from the columns. PercentileParamState makes sure the percentile resolution is both flexible enough to wait to be able to resolve the parameter AND applies the strict constraints that are required (constant Float32 or Float64).

The percentile is also included in state fields so that the merge_batch in the final Accumulator can process without any issues.

What is the testing strategy for this PR?

This new feature is covered by the sqllogictest cases added in aggregate.slt.

Unit tests have also been added to approx_percentile_cont.rs and percentile_cont.rs.

Are there any user-facing changes?

No breaking changes.

Benchark: ClickBench

Query main annarose_approx_percentile Change
QQuery 0 0.73 ms 0.79 ms 1.08x slower
QQuery 1 8.10 ms 8.91 ms 1.10x slower
QQuery 2 27.90 ms 30.59 ms 1.10x slower
QQuery 3 23.27 ms 23.89 ms no change
QQuery 4 157.25 ms 157.70 ms no change
QQuery 5 197.65 ms 201.26 ms no change
QQuery 6 0.72 ms 0.67 ms +1.08x faster
QQuery 7 8.20 ms 8.28 ms no change
QQuery 8 230.84 ms 215.32 ms +1.07x faster
QQuery 9 296.27 ms 312.37 ms 1.05x slower
QQuery 10 49.12 ms 47.66 ms no change
QQuery 11 58.86 ms 55.26 ms +1.07x faster
QQuery 12 198.45 ms 192.95 ms no change
QQuery 13 285.28 ms 280.02 ms no change
QQuery 14 195.67 ms 204.80 ms no change
QQuery 15 184.29 ms 180.74 ms no change
QQuery 16 434.20 ms 457.81 ms 1.05x slower
QQuery 17 476.52 ms 427.84 ms +1.11x faster
QQuery 18 912.71 ms 881.69 ms no change
QQuery 19 18.14 ms 19.41 ms 1.07x slower
QQuery 20 456.87 ms 463.23 ms no change
QQuery 21 468.67 ms 482.15 ms no change
QQuery 22 892.28 ms 896.13 ms no change
QQuery 23 2520.93 ms 2558.49 ms no change
QQuery 24 34.14 ms 33.50 ms no change
QQuery 25 99.14 ms 99.83 ms no change
QQuery 26 35.25 ms 34.51 ms no change
QQuery 27 467.74 ms 484.36 ms no change
QQuery 28 1931.71 ms 1945.50 ms no change
QQuery 29 29.16 ms 30.35 ms no change
QQuery 30 214.69 ms 209.17 ms no change
QQuery 31 196.43 ms 199.65 ms no change
QQuery 32 583.78 ms 614.36 ms 1.05x slower
QQuery 33 1078.73 ms 1145.79 ms 1.06x slower
QQuery 34 1073.15 ms 1117.56 ms no change
QQuery 35 182.87 ms 171.52 ms +1.07x faster
QQuery 36 46.27 ms 47.18 ms no change
QQuery 37 24.27 ms 24.03 ms no change
QQuery 38 29.58 ms 29.76 ms no change
QQuery 39 85.29 ms 86.14 ms no change
QQuery 40 8.23 ms 8.41 ms no change
QQuery 41 8.12 ms 8.47 ms no change
QQuery 42 6.72 ms 6.81 ms no change
Benchmark Summary
Total Time (main) 14238.19ms
Total Time (annarose_approx_percentile) 14404.87ms
Average Time (main) 331.12ms
Average Time (annarose_approx_percentile) 335.00ms
Queries Faster 5
Queries Slower 8
Queries with No Change 30
Queries with Failure 0

Memory profiling for clickbench_partitioned

this branch

Query Time (ms) Peak RSS Peak Commit Major Page Faults
0 5.43 84.0 MB 171.8 MB 0
1 11.45 119.6 MB 313.9 MB 0
2 27.44 240.8 MB 1536.1 MB 0
3 30.52 412.3 MB 1227.9 MB 0
4 173.88 2.8 GB 3.2 GB 0
5 193.60 2.5 GB 2.9 GB 0
6 3.36 93.0 MB 167.9 MB 0
7 10.66 128.1 MB 318.8 MB 0
8 219.80 3.4 GB 4.1 GB 0
9 268.65 2.4 GB 3.2 GB 0
10 45.84 780.3 MB 1809.8 MB 0
11 52.68 788.7 MB 1800.9 MB 0
12 183.80 2.5 GB 2.9 GB 0
13 266.55 3.0 GB 3.5 GB 0
14 191.93 2.4 GB 3.2 GB 0
15 185.03 3.0 GB 3.3 GB 0
16 422.42 6.4 GB 7.1 GB 0
17 404.75 6.1 GB 6.9 GB 0
18 861.29 12.2 GB 13.1 GB 0
19 19.20 362.3 MB 1118.0 MB 24
20 442.22 1171.1 MB 1429.2 MB 0
21 407.55 1836.8 MB 2.1 GB 0
22 763.73 2.5 GB 2.8 GB 0
23 2313.37 4.8 GB 5.5 GB 0
24 33.92 569.7 MB 959.2 MB 5
25 82.99 798.0 MB 1517.9 MB 0
26 35.10 599.1 MB 986.8 MB 0
27 392.34 1234.9 MB 1455.8 MB 0
28 1714.18 2.5 GB 2.7 GB 0
29 28.43 229.9 MB 1497.1 MB 0
30 191.47 2.2 GB 3.3 GB 0
31 182.56 2.8 GB 3.7 GB 0
32 1263.74 13.3 GB 16.2 GB 0
33 958.16 10.7 GB 10.9 GB 5
34 956.65 10.6 GB 10.9 GB 0
35 171.08 2.1 GB 2.6 GB 0
36 47.33 452.0 MB 800.8 MB 0
37 26.89 229.4 MB 544.9 MB 0
38 33.62 270.9 MB 503.8 MB 0
39 90.83 756.9 MB 1062.6 MB 0
40 11.41 208.3 MB 433.3 MB 0
41 11.47 170.3 MB 393.8 MB 0
42 10.48 142.8 MB 265.1 MB 0

main

Query Time (ms) Peak RSS Peak Commit Major Page Faults
0 4.76 94.7 MB 171.5 MB 0
1 11.22 120.7 MB 296.7 MB 0
2 32.05 244.2 MB 1533.8 MB 0
3 24.33 417.7 MB 1229.2 MB 0
4 175.85 2.8 GB 3.2 GB 0
5 207.07 2.5 GB 3.0 GB 0
6 3.46 94.3 MB 171.6 MB 0
7 11.08 129.4 MB 323.5 MB 0
8 223.08 3.4 GB 4.1 GB 0
9 288.63 2.4 GB 3.4 GB 0
10 48.79 792.1 MB 1767.0 MB 0
11 53.32 760.8 MB 1779.6 MB 0
12 189.17 2.6 GB 3.1 GB 0
13 274.96 3.0 GB 3.7 GB 0
14 202.74 2.6 GB 3.3 GB 0
15 208.83 3.0 GB 3.4 GB 0
16 576.37 6.3 GB 7.1 GB 0
17 623.87 6.5 GB 7.3 GB 0
18 1140.54 11.3 GB 13.1 GB 0
19 21.20 370.8 MB 1124.9 MB 26
20 507.91 1149.3 MB 1364.8 MB 0
21 479.85 1824.8 MB 2.1 GB 0
22 914.26 2.3 GB 2.7 GB 0
23 2757.47 4.6 GB 5.3 GB 0
24 41.85 591.0 MB 999.1 MB 0
25 91.00 763.3 MB 1500.8 MB 0
26 38.90 560.1 MB 980.6 MB 0
27 506.23 1319.5 MB 1550.4 MB 0
28 2119.47 2.6 GB 2.7 GB 0
29 34.79 213.7 MB 1267.2 MB 0
30 218.63 2.1 GB 3.1 GB 0
31 212.42 2.8 GB 3.7 GB 0
32 821.63 13.0 GB 16.1 GB 0
33 1162.42 10.5 GB 10.7 GB 14
34 1212.91 10.4 GB 10.6 GB 0
35 184.71 2.0 GB 2.5 GB 0
36 58.35 469.5 MB 845.9 MB 0
37 30.78 240.2 MB 545.1 MB 0
38 35.43 287.3 MB 485.4 MB 0
39 92.89 730.8 MB 1074.5 MB 0
40 11.87 204.7 MB 420.5 MB 0
41 11.43 171.2 MB 401.5 MB 0
42 10.57 146.6 MB 275.6 MB 0

@github-actions github-actions Bot added sqllogictest SQL Logic Tests (.slt) functions Changes to functions implementation labels Sep 15, 2026
@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Thank you for opening this pull request!

Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch).

Details
     Cloning apache/main
    Building datafusion-functions-aggregate v55.1.0 (current)
       Built [  37.509s] (current)
     Parsing datafusion-functions-aggregate v55.1.0 (current)
      Parsed [   0.047s] (current)
    Building datafusion-functions-aggregate v55.1.0 (baseline)
       Built [  30.690s] (baseline)
     Parsing datafusion-functions-aggregate v55.1.0 (baseline)
      Parsed [   0.044s] (baseline)
    Checking datafusion-functions-aggregate v55.1.0 -> v55.1.0 (no change; assume patch)
     Checked [   0.183s] 223 checks: 222 pass, 1 fail, 0 warn, 31 skip

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/inherent_method_missing.ron

Failed in:
  ApproxPercentileAccumulator::new, previously in file /home/runner/work/datafusion/datafusion/target/semver-checks/git-apache_main/d36c31538c01801b66126fedd2d9d0b0ceebda36/datafusion/functions-aggregate/src/approx_percentile_cont.rs:345
  ApproxPercentileAccumulator::new_with_max_size, previously in file /home/runner/work/datafusion/datafusion/target/semver-checks/git-apache_main/d36c31538c01801b66126fedd2d9d0b0ceebda36/datafusion/functions-aggregate/src/approx_percentile_cont.rs:353

     Summary semver requires new major version: 1 major and 0 minor checks failed
    Finished [  69.858s] datafusion-functions-aggregate
    Building datafusion-sqllogictest v55.1.0 (current)
       Built [  94.194s] (current)
     Parsing datafusion-sqllogictest v55.1.0 (current)
      Parsed [   0.015s] (current)
    Building datafusion-sqllogictest v55.1.0 (baseline)
       Built [  94.085s] (baseline)
     Parsing datafusion-sqllogictest v55.1.0 (baseline)
      Parsed [   0.016s] (baseline)
    Checking datafusion-sqllogictest v55.1.0 -> v55.1.0 (no change; assume patch)
     Checked [   0.108s] 223 checks: 223 pass, 31 skip
     Summary no semver update required
    Finished [ 191.078s] datafusion-sqllogictest

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Sep 15, 2026
@codecov-commenter

codecov-commenter commented Sep 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.38710% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.64%. Comparing base (c3ef346) to head (a1f030b).
⚠️ Report is 61 commits behind head on main.

Files with missing lines Patch % Lines
...afusion/functions-aggregate/src/percentile_cont.rs 87.83% 4 Missing and 14 partials ⚠️
datafusion/functions-aggregate/src/utils.rs 83.83% 12 Missing and 4 partials ⚠️
.../functions-aggregate/src/approx_percentile_cont.rs 95.55% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #25337      +/-   ##
==========================================
- Coverage   82.66%   82.64%   -0.02%     
==========================================
  Files        1147     1147              
  Lines      446357   452749    +6392     
  Branches   446357   452749    +6392     
==========================================
+ Hits       368971   374165    +5194     
- Misses      54997    55925     +928     
- Partials    22389    22659     +270     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dd-annarose
Can we do this at planning time instead? that would likely be must faster as it wouldn't have to inspect the inputs.

In the example you showed

SELECT
    approx_percentile_cont(y, m) AS median
FROM (
    SELECT t.x + 1 as y, 0.5 as m
    FROM (
        VALUES (10)
    ) AS t(x)
)

I think the subquery could be flattened to

SELECT
    approx_percentile_cont(t.x + 1, 0.5) AS median
    FROM 
    VALUES (10)

( in fact I am surprised it isn't)

@dd-annarose

Copy link
Copy Markdown
Contributor Author

@alamb We could, but we wouldn't support queries like this one (supported by Trino for example):

SELECT approx_percentile(x, m)
FROM (VALUES (10,0.1),(20,0.5),(30,0.9),(40,0.5)) AS t(x,m)

I don't have a Trino parity agenda, but this can be used more broadly when wanting to use a "real" column reference as percentile.

Happy to discuss!

@dd-annarose

Copy link
Copy Markdown
Contributor Author

Also: this is supported by spark

@asolimando asolimando left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dd-annarose thanks for working on this, I think it's good to support expressions beyond literals, as Postgres, Spark and Trino do. I left two comments, one minor potential perf improvement, and one blocking issue/error, the rest LGTM!

Comment thread datafusion/functions-aggregate/src/percentile_cont.rs Outdated
Comment thread datafusion/functions-aggregate/src/approx_percentile_cont.rs Outdated
@dd-annarose
dd-annarose force-pushed the annarose/approx_percentile branch 2 times, most recently from 147bbb8 to e778c2f Compare September 25, 2026 09:54

@asolimando asolimando left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@dd-annarose

Copy link
Copy Markdown
Contributor Author

@Jefffrey @alamb does it make more sense now? happy to provide more context!

Comment thread datafusion/functions-aggregate/src/percentile_cont.rs
Comment thread datafusion/functions-aggregate/src/approx_percentile_cont.rs Outdated
Comment thread datafusion/functions-aggregate/src/approx_percentile_cont.rs Outdated
Comment thread datafusion/functions-aggregate/src/approx_percentile_cont.rs Outdated
Comment thread datafusion/sqllogictest/test_files/aggregate.slt
Comment thread datafusion/sqllogictest/test_files/aggregate_memory_spill.slt
Comment thread datafusion/sqllogictest/test_files/aggregate.slt
Adds a PercentileParam and PercentileParamState to accept column references or projections for the percentile argument.

# Conflicts:
#	datafusion/functions-aggregate/src/percentile_cont.rs
replace non-deterministic metrics with <slt:ignore>
@gabotechs

Copy link
Copy Markdown
Contributor

run benchmark clickbench_partitioned

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5993730557-3058-6slkh 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing annarose/approx_percentile (44a9b2b) to d040501 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing annarose/approx_percentile (44a9b2b) to d040501 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and annarose_approx_percentile
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ annarose_approx_percentile ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │    1.25 ms │                    1.23 ms │     no change │
│ QQuery 1  │   11.63 ms │                   11.73 ms │     no change │
│ QQuery 2  │   36.35 ms │                   36.73 ms │     no change │
│ QQuery 3  │   30.96 ms │                   31.85 ms │     no change │
│ QQuery 4  │  231.67 ms │                  236.76 ms │     no change │
│ QQuery 5  │  270.09 ms │                  273.28 ms │     no change │
│ QQuery 6  │    1.30 ms │                    1.27 ms │     no change │
│ QQuery 7  │   12.64 ms │                   12.75 ms │     no change │
│ QQuery 8  │  328.69 ms │                  329.59 ms │     no change │
│ QQuery 9  │  466.34 ms │                  470.37 ms │     no change │
│ QQuery 10 │   65.17 ms │                   63.71 ms │     no change │
│ QQuery 11 │   75.86 ms │                   75.02 ms │     no change │
│ QQuery 12 │  262.45 ms │                  264.52 ms │     no change │
│ QQuery 13 │  353.11 ms │                  367.19 ms │     no change │
│ QQuery 14 │  277.00 ms │                  278.92 ms │     no change │
│ QQuery 15 │  281.81 ms │                  286.09 ms │     no change │
│ QQuery 16 │  610.11 ms │                  617.44 ms │     no change │
│ QQuery 17 │  616.43 ms │                  629.67 ms │     no change │
│ QQuery 18 │ 1276.58 ms │                 1261.09 ms │     no change │
│ QQuery 19 │   27.38 ms │                   27.48 ms │     no change │
│ QQuery 20 │  515.48 ms │                  518.18 ms │     no change │
│ QQuery 21 │  512.22 ms │                  514.47 ms │     no change │
│ QQuery 22 │  995.86 ms │                 1002.17 ms │     no change │
│ QQuery 23 │ 3042.22 ms │                 3138.95 ms │     no change │
│ QQuery 24 │   40.65 ms │                   41.47 ms │     no change │
│ QQuery 25 │  105.24 ms │                  104.68 ms │     no change │
│ QQuery 26 │   41.09 ms │                   41.11 ms │     no change │
│ QQuery 27 │  513.20 ms │                  508.68 ms │     no change │
│ QQuery 28 │ 2908.79 ms │                 2878.27 ms │     no change │
│ QQuery 29 │   41.13 ms │                   41.63 ms │     no change │
│ QQuery 30 │  305.42 ms │                  301.71 ms │     no change │
│ QQuery 31 │  276.10 ms │                  275.67 ms │     no change │
│ QQuery 32 │ 1104.73 ms │                  976.69 ms │ +1.13x faster │
│ QQuery 33 │ 1593.01 ms │                 1545.86 ms │     no change │
│ QQuery 34 │ 1582.18 ms │                 1598.09 ms │     no change │
│ QQuery 35 │  296.53 ms │                  295.63 ms │     no change │
│ QQuery 36 │   67.24 ms │                   67.98 ms │     no change │
│ QQuery 37 │   35.69 ms │                   35.16 ms │     no change │
│ QQuery 38 │   44.38 ms │                   40.06 ms │ +1.11x faster │
│ QQuery 39 │  138.45 ms │                  134.94 ms │     no change │
│ QQuery 40 │   14.78 ms │                   14.33 ms │     no change │
│ QQuery 41 │   13.64 ms │                   13.67 ms │     no change │
│ QQuery 42 │   13.31 ms │                   13.04 ms │     no change │
└───────────┴────────────┴────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                         ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                         │ 19438.18ms │
│ Total Time (annarose_approx_percentile)   │ 19379.16ms │
│ Average Time (HEAD)                       │   452.05ms │
│ Average Time (annarose_approx_percentile) │   450.68ms │
│ Queries Faster                            │          2 │
│ Queries Slower                            │          0 │
│ Queries with No Change                    │         41 │
│ Queries with Failure                      │          0 │
└───────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and annarose_approx_percentile
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                   HEAD ┃             annarose_approx_percentile ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │           1.25 / 3.98 ±5.37 / 14.72 ms │           1.23 / 4.03 ±5.50 / 15.02 ms │     no change │
│ QQuery 1  │         11.63 / 11.73 ±0.10 / 11.91 ms │         11.73 / 11.86 ±0.08 / 11.94 ms │     no change │
│ QQuery 2  │         36.35 / 36.55 ±0.15 / 36.76 ms │         36.73 / 36.97 ±0.14 / 37.13 ms │     no change │
│ QQuery 3  │         30.96 / 31.80 ±1.05 / 33.82 ms │         31.85 / 32.51 ±0.68 / 33.81 ms │     no change │
│ QQuery 4  │      231.67 / 235.24 ±3.93 / 242.51 ms │      236.76 / 238.43 ±2.45 / 243.24 ms │     no change │
│ QQuery 5  │      270.09 / 271.89 ±1.67 / 274.58 ms │      273.28 / 277.86 ±3.10 / 282.34 ms │     no change │
│ QQuery 6  │            1.30 / 1.44 ±0.23 / 1.90 ms │            1.27 / 1.43 ±0.24 / 1.89 ms │     no change │
│ QQuery 7  │         12.64 / 12.76 ±0.12 / 12.95 ms │         12.75 / 12.93 ±0.14 / 13.10 ms │     no change │
│ QQuery 8  │      328.69 / 332.81 ±4.76 / 341.05 ms │      329.59 / 336.81 ±5.99 / 345.91 ms │     no change │
│ QQuery 9  │      466.34 / 472.81 ±4.89 / 480.71 ms │      470.37 / 480.10 ±6.81 / 489.86 ms │     no change │
│ QQuery 10 │         65.17 / 65.94 ±0.96 / 67.75 ms │         63.71 / 65.09 ±1.33 / 67.59 ms │     no change │
│ QQuery 11 │         75.86 / 76.33 ±0.38 / 76.89 ms │         75.02 / 75.69 ±0.91 / 77.42 ms │     no change │
│ QQuery 12 │      262.45 / 265.63 ±2.02 / 268.77 ms │      264.52 / 271.56 ±4.90 / 279.50 ms │     no change │
│ QQuery 13 │     353.11 / 375.13 ±19.08 / 408.32 ms │     367.19 / 375.94 ±10.67 / 396.25 ms │     no change │
│ QQuery 14 │      277.00 / 283.75 ±5.02 / 289.34 ms │      278.92 / 285.79 ±4.23 / 290.47 ms │     no change │
│ QQuery 15 │      281.81 / 290.57 ±7.06 / 300.45 ms │      286.09 / 290.81 ±4.28 / 298.42 ms │     no change │
│ QQuery 16 │      610.11 / 622.83 ±8.06 / 632.82 ms │      617.44 / 633.32 ±9.69 / 644.78 ms │     no change │
│ QQuery 17 │      616.43 / 628.82 ±8.71 / 640.43 ms │      629.67 / 639.66 ±8.38 / 650.94 ms │     no change │
│ QQuery 18 │  1276.58 / 1306.48 ±30.03 / 1356.12 ms │  1261.09 / 1291.43 ±26.11 / 1330.69 ms │     no change │
│ QQuery 19 │        27.38 / 35.16 ±15.03 / 65.21 ms │         27.48 / 28.16 ±0.62 / 29.21 ms │ +1.25x faster │
│ QQuery 20 │      515.48 / 524.27 ±8.88 / 540.65 ms │      518.18 / 523.91 ±6.82 / 537.00 ms │     no change │
│ QQuery 21 │      512.22 / 521.15 ±5.84 / 529.96 ms │      514.47 / 523.46 ±5.00 / 528.73 ms │     no change │
│ QQuery 22 │    995.86 / 1004.29 ±6.90 / 1010.88 ms │  1002.17 / 1021.39 ±18.75 / 1053.91 ms │     no change │
│ QQuery 23 │ 3042.22 / 3230.03 ±105.29 / 3356.72 ms │ 3138.95 / 3382.75 ±319.54 / 4007.22 ms │     no change │
│ QQuery 24 │      40.65 / 124.24 ±80.11 / 246.24 ms │         41.47 / 43.65 ±2.13 / 47.67 ms │ +2.85x faster │
│ QQuery 25 │     105.24 / 145.07 ±77.25 / 299.56 ms │      104.68 / 105.53 ±0.54 / 106.17 ms │ +1.37x faster │
│ QQuery 26 │         41.09 / 42.48 ±1.44 / 45.04 ms │         41.11 / 41.32 ±0.20 / 41.67 ms │     no change │
│ QQuery 27 │      513.20 / 519.40 ±5.71 / 527.56 ms │     508.68 / 534.81 ±22.52 / 576.49 ms │     no change │
│ QQuery 28 │  2908.79 / 2922.57 ±16.02 / 2952.02 ms │  2878.27 / 2934.14 ±54.45 / 3026.51 ms │     no change │
│ QQuery 29 │         41.13 / 44.13 ±5.13 / 54.37 ms │        41.63 / 53.23 ±22.74 / 98.70 ms │  1.21x slower │
│ QQuery 30 │      305.42 / 314.71 ±7.90 / 325.04 ms │      301.71 / 311.93 ±9.82 / 329.90 ms │     no change │
│ QQuery 31 │     276.10 / 290.83 ±10.92 / 307.97 ms │     275.67 / 295.26 ±11.32 / 306.47 ms │     no change │
│ QQuery 32 │  1104.73 / 1122.61 ±16.54 / 1146.91 ms │   976.69 / 1047.30 ±44.59 / 1090.57 ms │ +1.07x faster │
│ QQuery 33 │  1593.01 / 1634.21 ±61.92 / 1756.52 ms │  1545.86 / 1633.09 ±71.15 / 1731.17 ms │     no change │
│ QQuery 34 │  1582.18 / 1632.60 ±52.41 / 1729.22 ms │  1598.09 / 1627.74 ±22.77 / 1655.78 ms │     no change │
│ QQuery 35 │     296.53 / 322.38 ±28.98 / 378.80 ms │    295.63 / 410.11 ±203.72 / 817.24 ms │  1.27x slower │
│ QQuery 36 │         67.24 / 75.97 ±6.69 / 87.58 ms │         67.98 / 72.27 ±2.86 / 76.38 ms │     no change │
│ QQuery 37 │         35.69 / 41.57 ±4.44 / 46.57 ms │         35.16 / 35.75 ±0.58 / 36.86 ms │ +1.16x faster │
│ QQuery 38 │         44.38 / 47.21 ±2.79 / 52.37 ms │         40.06 / 42.01 ±1.60 / 44.40 ms │ +1.12x faster │
│ QQuery 39 │      138.45 / 151.57 ±9.60 / 167.57 ms │     134.94 / 155.97 ±21.97 / 195.31 ms │     no change │
│ QQuery 40 │         14.78 / 17.08 ±3.72 / 24.50 ms │         14.33 / 14.79 ±0.36 / 15.40 ms │ +1.16x faster │
│ QQuery 41 │         13.64 / 15.37 ±2.79 / 20.91 ms │         13.67 / 13.82 ±0.22 / 14.25 ms │ +1.11x faster │
│ QQuery 42 │         13.31 / 15.25 ±3.46 / 22.15 ms │         13.04 / 13.29 ±0.15 / 13.48 ms │ +1.15x faster │
└───────────┴────────────────────────────────────────┴────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                         ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                         │ 20120.65ms │
│ Total Time (annarose_approx_percentile)   │ 20227.92ms │
│ Average Time (HEAD)                       │   467.92ms │
│ Average Time (annarose_approx_percentile) │   470.42ms │
│ Queries Faster                            │          9 │
│ Queries Slower                            │          2 │
│ Queries with No Change                    │         32 │
│ Queries with Failure                      │          0 │
└───────────────────────────────────────────┴────────────┘

Resource Usage

clickbench_partitioned — base (merge-base)

Metric Value
Wall time 105.0s
Peak memory 17.1 GiB
Avg memory 5.6 GiB
CPU user 992.3s
CPU sys 96.5s
Peak spill 0 B

clickbench_partitioned — branch

Metric Value
Wall time 105.0s
Peak memory 17.1 GiB
Avg memory 5.8 GiB
CPU user 995.4s
CPU sys 95.1s
Peak spill 0 B

File an issue against this benchmark runner

@github-actions github-actions Bot added documentation Improvements or additions to documentation sql SQL Planner development-process Related to development process of DataFusion logical-expr Logical plan and expressions physical-expr Changes to the physical-expr crates optimizer Optimizer rules core Core DataFusion crate substrait Changes to the substrait crate labels Oct 5, 2026
@github-actions github-actions Bot added execution Related to the execution crate proto Related to proto crate datasource Changes to the datasource crate ffi Changes to the ffi crate physical-plan Changes to the physical-plan crate spark labels Oct 5, 2026
cleaner code
@dd-annarose
dd-annarose force-pushed the annarose/approx_percentile branch from 0aa3562 to 8088f8c Compare October 5, 2026 14:50
@github-actions github-actions Bot removed documentation Improvements or additions to documentation sql SQL Planner development-process Related to development process of DataFusion logical-expr Logical plan and expressions physical-expr Changes to the physical-expr crates optimizer Optimizer rules core Core DataFusion crate substrait Changes to the substrait crate catalog Related to the catalog crate common Related to common crate execution Related to the execution crate proto Related to proto crate datasource Changes to the datasource crate ffi Changes to the ffi crate physical-plan Changes to the physical-plan crate spark labels Oct 5, 2026
@dd-annarose
dd-annarose requested a review from gabotechs October 5, 2026 14:54
@gabotechs

gabotechs commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Also: this is supported by spark

Regarding this, I'm seeing that this is actually not supported by Spark. Did a quick test with a local Spark container running 4.0.1 and this is what I'm seeing:

Percentile argument PR behavior Spark 4.0.1
Literal or 0.25 + 0.25 Accepted Accepted
Projected literal, SELECT …, 0.5 AS m Accepted NON_FOLDABLE_INPUT
Column containing only 0.5 Accepted NON_FOLDABLE_INPUT
Column constant within each group Accepted NON_FOLDABLE_INPUT
Column with empty input Returns NULL NON_FOLDABLE_INPUT

In the doc you linked https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.approx_percentile.html#pyspark-sql-functions-approx-percentile, it looks like that Column is not an actual "column" as known in relational algebra, is just a Python class that can reference to a literal or an expression.

For reference here is the Spark code that rejects these kind of queries in case of a NON_FOLDABLE_INPUT.

Given that this is supported by Trino, and that it's still API compatible with Spark and Postgres, I'd still be in favor of merging this, however, I'm not comfortable just pulling this in without an extra pair of eyes from a PMC. cc @alamb as you reviewed this PR before.

@dd-annarose dd-annarose closed this Oct 8, 2026
@dd-annarose dd-annarose reopened this Oct 8, 2026
@dd-annarose

Copy link
Copy Markdown
Contributor Author

(sorry I closed the wrong PR 🤦🏻‍♀️)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto detected api change Auto detected API change functions Changes to functions implementation sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support column reference as percentile arg for percentile_cont and approx_percentile_cont

6 participants