Skip to content

perf: reuse the projected equivalence group when only child orderings change - #24445

Open
zhuqi-lucas wants to merge 8 commits into
apache:mainfrom
zhuqi-lucas:qizhu/reuse-eq-group-on-child-swap
Open

perf: reuse the projected equivalence group when only child orderings change#24445
zhuqi-lucas wants to merge 8 commits into
apache:mainfrom
zhuqi-lucas:qizhu/reuse-eq-group-on-child-swap

Conversation

@zhuqi-lucas

@zhuqi-lucas zhuqi-lucas commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Which issue does this close?

Closes #24478.

Rationale for this change

replace_children_if_necessary already short-circuits two cases: identical child pointers, and identical child PlanProperties pointers. A rule that inserts a sort below a projection satisfies neither, because the child is a new object and so its properties pointer differs. Its equivalence group, however, is unchanged: sorting changes which orderings hold, not which expressions are equal to one another.

Recompute therefore re-projects a group identical to the one the projection already holds. EquivalenceGroup::project is a pure function of the group and the mapping, so when both are unchanged the previous result can be handed back instead of recomputed.

This matters on plans with many wide projections, because the recompute is repeated for every projection above the inserted sort, on every pass of the rule.

What changes are included in this PR?

  1. EquivalenceGroup gains PartialEq, comparing classes. map is an index into classes and carries no additional information.
  2. EquivalenceProperties::project splits, so project_with_eq_group can take an already-projected group. Orderings are still derived, since they are precisely what changes when a sort appears below.
  3. ProjectionExec::replace_children compares the old and new child equivalence groups on the Recompute path and, when they match, reuses the cached group.

The check is local to ProjectionExec. No new ChildrenPropertiesMode variant and no change to the shared path, so other operators are unaffected.

Measurements

A query over a 1191-line view with 38 SELECTs, 117 CASE expressions and 7 joins across 11 tables. Ten warm samples per configuration, identical build flags, the only variable being this patch:

before (median) after (median)
EnforceSorting 197.8ms 90.1ms −54%
optimizer rules 338.1ms 214.6ms −37%
planning wall 420.6ms 299.0ms −29%

The ranges do not overlap: 196.9–199.2 against 88.8–91.0. Logical rules are unchanged across the two configurations, which acts as the control: the saving lands in the physical phase and nowhere else. EnforceDistribution improves as well, since it rebuilds the same projections.

The saving scales with projection count times expression size times rule passes, so plans with narrow projections should see little. I expect sql_planner to show a small delta for that reason.

Are there any user-facing changes?

No. Plans are unchanged.

Testing

datafusion-physical-expr 1594, datafusion-physical-plan 1716, datafusion-physical-optimizer 33, datafusion-optimizer 760, datafusion-common 550, datafusion core 442, and all 502 sqllogictest files. No test or expected plan was modified.

Worth flagging for review: an earlier revision passed the projected equivalence properties to Partitioning::project where compute_properties passes the input's. Every unit test stayed green; only range_partitioning.slt caught it, via the case asserting that a join preserving Range partitioning lets the aggregate above it skip a Hash repartition. It produced a worse plan rather than a wrong answer, which is why nothing else noticed.

Follow-up

Holding the equivalence group behind an Arc would reduce the comparison to Arc::ptr_eq and make EquivalenceProperties::clone cheaper, which happens on every SortExec construction. It touches every site that mutates the group, so it seemed better kept separate. The structural comparison's cost is already inside the numbers above.

@github-actions github-actions Bot added physical-expr Changes to the physical-expr crates physical-plan Changes to the physical-plan crate labels Aug 18, 2026
@codecov-commenter

codecov-commenter commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.52601% with 57 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.24%. Comparing base (c429919) to head (95cc536).

Files with missing lines Patch % Lines
datafusion/physical-plan/src/projection.rs 84.93% 10 Missing and 23 partials ⚠️
datafusion/physical-expr/src/equivalence/class.rs 70.58% 0 Missing and 15 partials ⚠️
...on/physical-expr/src/equivalence/properties/mod.rs 88.15% 0 Missing and 9 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24445      +/-   ##
==========================================
- Coverage   81.24%   81.24%   -0.01%     
==========================================
  Files        1113     1113              
  Lines      392744   393086     +342     
  Branches   392744   393086     +342     
==========================================
+ Hits       319090   319367     +277     
- Misses      54900    54915      +15     
- Partials    18754    18804      +50     

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

… change

`replace_children_if_necessary` already short-circuits two cases: identical
child pointers, and identical child `PlanProperties` pointers. Inserting a
sort below a projection satisfies neither — the child is a new object, so its
properties pointer differs — yet the child's equivalence group is unchanged.
Sorting changes which orderings hold, not which expressions are equal.

`Recompute` therefore re-projects a group identical to the one the projection
already holds. `EquivalenceGroup::project` is a pure function of the group and
the mapping, so when both are unchanged the previous result can be handed back
instead.

`ProjectionExec::replace_children` now compares the old and new child
equivalence groups on the `Recompute` path and, when they match, reuses the
cached group and derives only the orderings. The check is local to
`ProjectionExec`: no new `ChildrenPropertiesMode` variant, and no change to the
shared path, so other operators are unaffected.

Supporting changes: `EquivalenceGroup` gains `PartialEq` (comparing `classes`,
since `map` is an index into them), and `EquivalenceProperties::project` splits
so `project_with_eq_group` can take an already-projected group.

Measured on a query over a 1191-line view with 38 SELECTs, 117 CASE
expressions and 7 joins across 11 tables. Ten warm samples per
configuration, same build flags, the only variable being this patch:

                      before (median)   after (median)
    EnforceSorting          197.8ms           90.1ms   -54%
    optimizer rules         338.1ms          214.6ms   -37%
    planning wall           420.6ms          299.0ms   -29%

The two ranges do not overlap (196.9-199.2 against 88.8-91.0). Logical rules
are unchanged, which is the control: the saving lands in the physical phase and
nowhere else. `EnforceDistribution` improves as well, since it rebuilds the
same projections.

The saving scales with projection count times expression size times rule
passes, so plans with narrow projections will see little.
@zhuqi-lucas
zhuqi-lucas force-pushed the qizhu/reuse-eq-group-on-child-swap branch from d1e682e to 82edbc3 Compare August 18, 2026 06:50
@zhuqi-lucas

Copy link
Copy Markdown
Contributor Author

run benchmark sql_planner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5324655706-1637-dml25 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 qizhu/reuse-eq-group-on-child-swap (82edbc3) to 6eaca8b (merge-base) diff

Run configuration
run benchmark sql_planner

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 qizhu/reuse-eq-group-on-child-swap (82edbc3) to 6eaca8b (merge-base) diff

Run configuration
run benchmark sql_planner
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

group                                                 HEAD                                   qizhu_reuse-eq-group-on-child-swap
-----                                                 ----                                   ----------------------------------
logical_aggregate_with_join                           1.00    450.4±1.62µs        ? ?/sec    1.00    449.9±1.39µs        ? ?/sec
logical_correlated_subquery_exists                    1.00    283.1±0.75µs        ? ?/sec    1.00    284.0±1.50µs        ? ?/sec
logical_correlated_subquery_in                        1.00    285.9±0.83µs        ? ?/sec    1.00    286.1±0.66µs        ? ?/sec
logical_distinct_many_columns                         1.00    575.9±1.44µs        ? ?/sec    1.00    573.5±1.10µs        ? ?/sec
logical_join_4_with_agg_and_filter                    1.00    254.5±2.47µs        ? ?/sec    1.00    253.6±1.86µs        ? ?/sec
logical_join_8_with_agg_sort_limit                    1.00    427.1±4.67µs        ? ?/sec    1.00    428.7±2.52µs        ? ?/sec
logical_join_chain_16                                 1.00    676.0±3.97µs        ? ?/sec    1.00    673.2±4.15µs        ? ?/sec
logical_join_chain_4                                  1.00    122.9±0.52µs        ? ?/sec    1.00    122.4±0.41µs        ? ?/sec
logical_join_chain_8                                  1.00    250.0±1.30µs        ? ?/sec    1.00    248.9±1.07µs        ? ?/sec
logical_multiple_subqueries                           1.00    517.9±2.24µs        ? ?/sec    1.01    523.8±8.38µs        ? ?/sec
logical_nested_cte_4_levels                           1.00    260.5±1.35µs        ? ?/sec    1.02    264.9±0.89µs        ? ?/sec
logical_plan_struct_join_agg_sort                     1.03    182.2±1.00µs        ? ?/sec    1.00    177.8±1.29µs        ? ?/sec
logical_plan_tpcds_all                                1.00     93.9±0.18ms        ? ?/sec    1.00     94.2±0.18ms        ? ?/sec
logical_plan_tpch_all                                 1.00      6.6±0.03ms        ? ?/sec    1.00      6.6±0.02ms        ? ?/sec
logical_scalar_subquery                               1.00    306.9±4.18µs        ? ?/sec    1.01    308.6±1.23µs        ? ?/sec
logical_select_all_from_1000                          1.00    105.0±0.11ms        ? ?/sec    1.00    104.5±0.11ms        ? ?/sec
logical_select_one_from_700                           1.00    326.2±2.24µs        ? ?/sec    1.00    324.9±2.12µs        ? ?/sec
logical_trivial_join_high_numbered_columns            1.00    283.9±0.59µs        ? ?/sec    1.00    283.7±0.84µs        ? ?/sec
logical_trivial_join_low_numbered_columns             1.00    271.9±0.79µs        ? ?/sec    1.00    271.0±0.74µs        ? ?/sec
logical_union_4_branches                              1.00    422.0±4.00µs        ? ?/sec    1.01    425.5±1.19µs        ? ?/sec
logical_union_8_branches                              1.00    804.7±2.32µs        ? ?/sec    1.01    808.8±2.56µs        ? ?/sec
logical_wide_aggregate_100_exprs                      1.00      4.5±0.01ms        ? ?/sec    1.00      4.5±0.01ms        ? ?/sec
logical_wide_case_50_exprs                            1.00      2.4±0.01ms        ? ?/sec    1.00      2.4±0.00ms        ? ?/sec
logical_wide_filter_200_predicates                    1.00   1307.6±8.06µs        ? ?/sec    1.01   1316.7±7.90µs        ? ?/sec
logical_wide_filter_50_predicates                     1.00    387.7±2.57µs        ? ?/sec    1.00    389.5±2.24µs        ? ?/sec
optimizer_correlated_exists                           1.01    249.8±0.56µs        ? ?/sec    1.00    248.3±0.94µs        ? ?/sec
optimizer_join_4_with_agg_filter                      1.00    483.4±1.09µs        ? ?/sec    1.01    488.7±1.54µs        ? ?/sec
optimizer_join_chain_4                                1.01    188.7±0.41µs        ? ?/sec    1.00    187.7±0.57µs        ? ?/sec
optimizer_join_chain_8                                1.00    574.4±1.30µs        ? ?/sec    1.00    576.5±1.49µs        ? ?/sec
optimizer_select_all_from_1000                        1.00      6.8±0.01ms        ? ?/sec    1.00      6.8±0.01ms        ? ?/sec
optimizer_select_one_from_700                         1.01    254.2±0.58µs        ? ?/sec    1.00    252.9±0.72µs        ? ?/sec
optimizer_tpcds_all                                   1.01    320.0±1.79ms        ? ?/sec    1.00    318.4±0.36ms        ? ?/sec
optimizer_tpch_all                                    1.00     18.1±0.04ms        ? ?/sec    1.00     18.1±0.04ms        ? ?/sec
optimizer_wide_aggregate_100                          1.00      2.3±0.00ms        ? ?/sec    1.00      2.3±0.00ms        ? ?/sec
optimizer_wide_filter_200                             1.00      3.7±0.01ms        ? ?/sec    1.00      3.7±0.01ms        ? ?/sec
physical_intersection                                 1.00    597.5±1.68µs        ? ?/sec    1.01    601.2±2.49µs        ? ?/sec
physical_join_consider_sort                           1.00   1055.3±7.26µs        ? ?/sec    1.00   1050.3±3.73µs        ? ?/sec
physical_join_distinct                                1.01    265.4±0.64µs        ? ?/sec    1.00    263.9±0.66µs        ? ?/sec
physical_many_self_joins                              1.00      7.6±0.02ms        ? ?/sec    1.00      7.6±0.02ms        ? ?/sec
physical_plan_clickbench_all                          1.00    129.9±0.41ms        ? ?/sec    1.00    129.7±0.42ms        ? ?/sec
physical_plan_clickbench_q1                           1.00   1407.3±7.49µs        ? ?/sec    1.00   1400.8±8.07µs        ? ?/sec
physical_plan_clickbench_q10                          1.00      2.1±0.01ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q11                          1.00      2.2±0.01ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q12                          1.00      2.3±0.01ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
physical_plan_clickbench_q13                          1.00      2.1±0.01ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q14                          1.00      2.3±0.01ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
physical_plan_clickbench_q15                          1.00      2.1±0.01ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q16                          1.00   1820.3±7.74µs        ? ?/sec    1.00   1824.5±7.84µs        ? ?/sec
physical_plan_clickbench_q17                          1.00   1869.4±7.14µs        ? ?/sec    1.00   1876.9±6.83µs        ? ?/sec
physical_plan_clickbench_q18                          1.00   1696.7±8.08µs        ? ?/sec    1.01   1717.6±8.05µs        ? ?/sec
physical_plan_clickbench_q19                          1.00      2.1±0.01ms        ? ?/sec    1.01      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q2                           1.01   1815.2±7.62µs        ? ?/sec    1.00   1804.7±7.01µs        ? ?/sec
physical_plan_clickbench_q20                          1.00   1539.6±7.60µs        ? ?/sec    1.02   1563.6±7.41µs        ? ?/sec
physical_plan_clickbench_q21                          1.00   1790.6±6.82µs        ? ?/sec    1.01   1811.5±7.29µs        ? ?/sec
physical_plan_clickbench_q22                          1.00      2.2±0.01ms        ? ?/sec    1.01      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q23                          1.01      2.4±0.01ms        ? ?/sec    1.00      2.4±0.01ms        ? ?/sec
physical_plan_clickbench_q24                          1.02      6.8±0.03ms        ? ?/sec    1.00      6.7±0.02ms        ? ?/sec
physical_plan_clickbench_q25                          1.03  1970.7±10.12µs        ? ?/sec    1.00   1915.9±7.72µs        ? ?/sec
physical_plan_clickbench_q26                          1.00   1769.6±7.47µs        ? ?/sec    1.00   1765.4±8.05µs        ? ?/sec
physical_plan_clickbench_q27                          1.01   1977.7±7.51µs        ? ?/sec    1.00   1967.0±6.20µs        ? ?/sec
physical_plan_clickbench_q28                          1.00      2.4±0.01ms        ? ?/sec    1.00      2.4±0.01ms        ? ?/sec
physical_plan_clickbench_q29                          1.00      2.6±0.01ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
physical_plan_clickbench_q3                           1.01   1705.0±7.21µs        ? ?/sec    1.00   1692.6±7.48µs        ? ?/sec
physical_plan_clickbench_q30                          1.02     15.7±0.05ms        ? ?/sec    1.00     15.4±0.26ms        ? ?/sec
physical_plan_clickbench_q31                          1.00      2.5±0.01ms        ? ?/sec    1.00      2.5±0.01ms        ? ?/sec
physical_plan_clickbench_q32                          1.00      2.5±0.01ms        ? ?/sec    1.00      2.5±0.01ms        ? ?/sec
physical_plan_clickbench_q33                          1.00      2.1±0.01ms        ? ?/sec    1.00      2.1±0.02ms        ? ?/sec
physical_plan_clickbench_q34                          1.00   1828.3±7.16µs        ? ?/sec    1.01  1838.2±16.27µs        ? ?/sec
physical_plan_clickbench_q35                          1.00   1876.9±6.49µs        ? ?/sec    1.00   1871.8±8.93µs        ? ?/sec
physical_plan_clickbench_q36                          1.00      2.2±0.01ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q37                          1.00      2.6±0.01ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
physical_plan_clickbench_q38                          1.00      2.6±0.01ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
physical_plan_clickbench_q39                          1.00      2.6±0.01ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
physical_plan_clickbench_q4                           1.01   1516.5±6.21µs        ? ?/sec    1.00   1505.9±8.56µs        ? ?/sec
physical_plan_clickbench_q40                          1.00      3.4±0.01ms        ? ?/sec    1.00      3.4±0.01ms        ? ?/sec
physical_plan_clickbench_q41                          1.00      2.9±0.01ms        ? ?/sec    1.00      2.9±0.01ms        ? ?/sec
physical_plan_clickbench_q42                          1.00      3.1±0.01ms        ? ?/sec    1.01      3.1±0.01ms        ? ?/sec
physical_plan_clickbench_q43                          1.00      3.2±0.01ms        ? ?/sec    1.02      3.3±0.02ms        ? ?/sec
physical_plan_clickbench_q44                          1.00   1586.4±7.10µs        ? ?/sec    1.02   1623.4±9.13µs        ? ?/sec
physical_plan_clickbench_q45                          1.00   1593.1±7.22µs        ? ?/sec    1.02   1625.4±8.23µs        ? ?/sec
physical_plan_clickbench_q46                          1.00   1921.2±6.73µs        ? ?/sec    1.02   1957.5±8.66µs        ? ?/sec
physical_plan_clickbench_q47                          1.01      2.7±0.01ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
physical_plan_clickbench_q48                          1.01      2.8±0.01ms        ? ?/sec    1.00      2.8±0.01ms        ? ?/sec
physical_plan_clickbench_q49                          1.00      2.9±0.01ms        ? ?/sec    1.00      2.9±0.01ms        ? ?/sec
physical_plan_clickbench_q5                           1.00   1660.0±8.10µs        ? ?/sec    1.00  1652.0±13.88µs        ? ?/sec
physical_plan_clickbench_q50                          1.00      2.7±0.01ms        ? ?/sec    1.00      2.7±0.01ms        ? ?/sec
physical_plan_clickbench_q51                          1.00      2.1±0.01ms        ? ?/sec    1.01      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q6                           1.00   1639.0±5.92µs        ? ?/sec    1.02  1668.4±14.79µs        ? ?/sec
physical_plan_clickbench_q7                           1.00   1455.1±6.90µs        ? ?/sec    1.01  1468.6±10.57µs        ? ?/sec
physical_plan_clickbench_q8                           1.00   1953.6±6.20µs        ? ?/sec    1.01  1966.8±12.57µs        ? ?/sec
physical_plan_clickbench_q9                           1.00   1972.9±8.63µs        ? ?/sec    1.00  1982.0±14.67µs        ? ?/sec
physical_plan_struct_join_agg_sort                    1.01   1357.6±2.65µs        ? ?/sec    1.00   1343.8±3.40µs        ? ?/sec
physical_plan_tpcds_all                               1.02    737.9±3.39ms        ? ?/sec    1.00    726.9±1.07ms        ? ?/sec
physical_plan_tpch_all                                1.01     45.9±0.08ms        ? ?/sec    1.00     45.6±0.07ms        ? ?/sec
physical_plan_tpch_q1                                 1.01   1615.5±3.02µs        ? ?/sec    1.00   1603.8±2.89µs        ? ?/sec
physical_plan_tpch_q10                                1.02      2.9±0.01ms        ? ?/sec    1.00      2.8±0.02ms        ? ?/sec
physical_plan_tpch_q11                                1.01      2.3±0.05ms        ? ?/sec    1.00      2.3±0.00ms        ? ?/sec
physical_plan_tpch_q12                                1.00  1295.8±18.16µs        ? ?/sec    1.01   1307.1±2.43µs        ? ?/sec
physical_plan_tpch_q13                                1.00   1070.7±5.06µs        ? ?/sec    1.02   1088.4±4.40µs        ? ?/sec
physical_plan_tpch_q14                                1.00   1473.9±3.34µs        ? ?/sec    1.00   1476.0±6.32µs        ? ?/sec
physical_plan_tpch_q16                                1.00  1665.4±11.68µs        ? ?/sec    1.01   1676.8±6.94µs        ? ?/sec
physical_plan_tpch_q17                                1.00   1705.2±4.98µs        ? ?/sec    1.00   1710.2±8.83µs        ? ?/sec
physical_plan_tpch_q18                                1.00      2.0±0.00ms        ? ?/sec    1.01      2.0±0.01ms        ? ?/sec
physical_plan_tpch_q19                                1.00   1937.0±2.90µs        ? ?/sec    1.01  1964.8±10.73µs        ? ?/sec
physical_plan_tpch_q2                                 1.02      3.7±0.03ms        ? ?/sec    1.00      3.7±0.01ms        ? ?/sec
physical_plan_tpch_q20                                1.00      2.2±0.00ms        ? ?/sec    1.01      2.2±0.01ms        ? ?/sec
physical_plan_tpch_q21                                1.00      2.9±0.00ms        ? ?/sec    1.00      2.9±0.01ms        ? ?/sec
physical_plan_tpch_q22                                1.00   1535.1±3.40µs        ? ?/sec    1.00   1535.5±3.15µs        ? ?/sec
physical_plan_tpch_q3                                 1.01  1955.9±13.44µs        ? ?/sec    1.00   1927.4±3.56µs        ? ?/sec
physical_plan_tpch_q4                                 1.01   1253.5±6.83µs        ? ?/sec    1.00   1240.4±3.91µs        ? ?/sec
physical_plan_tpch_q5                                 1.01      2.8±0.01ms        ? ?/sec    1.00      2.8±0.00ms        ? ?/sec
physical_plan_tpch_q6                                 1.01    657.0±1.34µs        ? ?/sec    1.00    649.0±1.86µs        ? ?/sec
physical_plan_tpch_q7                                 1.01      2.9±0.01ms        ? ?/sec    1.00      2.9±0.02ms        ? ?/sec
physical_plan_tpch_q8                                 1.00      4.0±0.01ms        ? ?/sec    1.00      3.9±0.03ms        ? ?/sec
physical_plan_tpch_q9                                 1.02      2.8±0.00ms        ? ?/sec    1.00      2.7±0.02ms        ? ?/sec
physical_select_aggregates_from_200                   1.00     15.6±0.03ms        ? ?/sec    1.00     15.6±0.04ms        ? ?/sec
physical_select_all_from_1000                         1.00    116.0±0.13ms        ? ?/sec    1.00    115.5±0.14ms        ? ?/sec
physical_select_one_from_700                          1.00    765.6±1.84µs        ? ?/sec    1.00    763.0±3.32µs        ? ?/sec
physical_sorted_union_order_by_10_int64               1.01      4.3±0.01ms        ? ?/sec    1.00      4.2±0.01ms        ? ?/sec
physical_sorted_union_order_by_10_uint64              1.05      9.2±0.02ms        ? ?/sec    1.00      8.8±0.02ms        ? ?/sec
physical_sorted_union_order_by_50_int64               1.01     96.8±0.22ms        ? ?/sec    1.00     95.5±0.30ms        ? ?/sec
physical_sorted_union_order_by_50_uint64              1.10    404.4±1.87ms        ? ?/sec    1.00    368.9±0.93ms        ? ?/sec
physical_theta_join_consider_sort                     1.00   1077.1±7.15µs        ? ?/sec    1.00   1077.8±2.61µs        ? ?/sec
physical_unnest_to_join                               1.00    637.3±1.99µs        ? ?/sec    1.00    639.9±1.78µs        ? ?/sec
physical_window_function_partition_by_12_on_values    1.01    729.1±1.53µs        ? ?/sec    1.00    723.2±1.58µs        ? ?/sec
physical_window_function_partition_by_30_on_values    1.02   1436.8±4.48µs        ? ?/sec    1.00   1410.1±3.29µs        ? ?/sec
physical_window_function_partition_by_4_on_values     1.01    455.9±1.51µs        ? ?/sec    1.00    452.6±1.17µs        ? ?/sec
physical_window_function_partition_by_7_on_values     1.00    553.6±1.84µs        ? ?/sec    1.00    550.9±1.59µs        ? ?/sec
physical_window_function_partition_by_8_on_values     1.01    592.4±1.87µs        ? ?/sec    1.00    589.3±2.07µs        ? ?/sec
with_param_values_many_columns                        1.01    437.1±2.57µs        ? ?/sec    1.00    433.1±2.17µs        ? ?/sec

Resource Usage

sql_planner — base (merge-base)

Metric Value
Wall time 2400.5s
Peak memory 127.8 MiB
Avg memory 65.1 MiB
CPU user 1897.4s
CPU sys 1.3s
Peak spill 0 B

sql_planner — branch

Metric Value
Wall time 2395.5s
Peak memory 130.1 MiB
Avg memory 66.6 MiB
CPU user 1888.5s
CPU sys 1.5s
Peak spill 0 B

File an issue against this benchmark runner

Adds unit tests for the fast path and the invariant it rests on.

`EquivalenceGroup`'s new `PartialEq`: equal classes compare equal however
they were arrived at (a bridged `a = b`, `b = c` matches a directly stated
one), member order within a class is immaterial, and differing or widened
classes compare unequal.

`EquivalenceProperties::project_with_eq_group`: handing back exactly the
group `project` would have computed reproduces it in full -- group,
orderings, constraints and schema all match. A second test passes an empty
group to confirm the argument is actually consumed rather than ignored.

`ProjectionExec::replace_children`: a sort below the projection changes the
orderings but not the equivalence group, and the resulting properties match
building the projection from scratch. A child that equates a different pair
must not inherit the cached group, which is the case that would be unsound;
inverting the guard to always reuse makes that test fail. `Keep` mode is
covered too, and a separate test pins the premise that sorting leaves the
equivalence group untouched, so a change in that behaviour fails there
first rather than silently weakening the fast path.
@zhuqi-lucas
zhuqi-lucas marked this pull request as ready for review August 19, 2026 02:33
Copilot AI lite review requested due to automatic review settings August 19, 2026 02:33

Copilot AI 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.

Pull request overview

This PR optimizes physical plan property recomputation for ProjectionExec by reusing an already-projected equivalence group when the only upstream change is to child orderings (e.g., inserting a SortExec below a projection). This reduces repeated EquivalenceGroup::project work during physical optimization passes while keeping plan semantics unchanged.

Changes:

  • Add PartialEq for EquivalenceGroup (comparing only equivalence classes).
  • Split EquivalenceProperties::project to allow project_with_eq_group, reusing a previously projected equivalence group while still re-deriving orderings.
  • Add a ProjectionExec fast path in replace_children(Recompute) to reuse the cached projected equivalence group when the child’s equivalence group is unchanged, plus targeted regression tests.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
datafusion/physical-plan/src/projection.rs Adds a replace_children fast path to reuse cached projected equivalence group when only orderings change; adds tests covering the new behavior.
datafusion/physical-expr/src/equivalence/properties/mod.rs Introduces project_with_eq_group and refactors project to delegate, enabling reuse of an already-projected group while recomputing orderings/constraints.
datafusion/physical-expr/src/equivalence/class.rs Implements PartialEq for EquivalenceGroup based on classes (treating map as derived/index-only), with tests validating intended equality behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

`EquivalenceGroup`'s new `PartialEq` compared `classes` positionally. `classes`
is a `Vec` but its order carries no meaning -- `remove_class_at_idx` uses
`swap_remove` -- so two groups describing exactly the same equalities could
compare unequal depending on how they were built. That is a trap for any caller
treating this as a semantic check, and it also made the projection fast path
needlessly conservative. It now compares the classes as the sets they are.

`test_project_with_eq_group_derives_orderings_from_the_caller_group` was
vacuous: it asserted on `eq_group()`, which stores the argument verbatim, so it
would have passed even if the group were ignored everywhere else. Asserting on
`oeq_class()` would not have helped either, since that is built from the
projected orderings and never consults the group. It now asserts on behaviour,
and picks the probe carefully: `projected_orderings` resolves `[a ASC]` to
`[c1 ASC]` by itself, so asking whether `c1` is ordered proves nothing. Asking
about `a1` does, because reaching that conclusion requires the supplied group to
say `a1 = c1`.

`assert_same_properties` compared partitioning through derived `Debug`, which
changes with any field addition. It now compares the partition count and the
explicit `Display` form.

Both fixes are covered: reverting the comparison to positional makes
`test_equivalence_group_eq_ignores_class_order` fail.
@zhuqi-lucas

Copy link
Copy Markdown
Contributor Author

run benchmark sql_planner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5338111275-1718-59rxw 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 qizhu/reuse-eq-group-on-child-swap (09d9cd2) to c429919 (merge-base) diff

Run configuration
run benchmark sql_planner

Results will be posted here when complete


File an issue against this benchmark runner

The guard compares the old and new child equivalence groups, but
`EquivalenceGroup::project` is a pure function of *two* arguments. The
second, the projection mapping, was only implicitly unchanged. Document
why, and cover it.

The mapping comes from `projector.projection()`, carried over untouched, and
from the child's schema, which `ProjectionMapping::try_new` consults only for
field names and indices -- never for types or nullability. A child differing
only in nullability therefore keeps the same mapping. A child that renamed or
reordered those fields would change the group as well, since its members are
`Column`s carrying those names, so the comparison already rejects it; were one
to slip through, `try_new`'s name assertion errors out rather than letting a
stale group into the plan.

The new test swaps in a child differing only in nullability and asserts the
fast path agrees with `try_from_projector`, the path it replaces. It compares
against that rather than a freshly built projection deliberately:
`replace_children` carries the existing `Projector` over, so the output schema
stays as it was, while `try_new` derives a new one from the new child. That
difference belongs to `replace_children` and predates this change, so the
meaningful contract is that its two paths agree. Handing the fast path an
empty group makes the test fail.
The test swapped in a child that made fields nullable. That is the one
direction `is_allowed_field_change` forbids a physical optimizer rule from
taking: it permits a field to become non-nullable, never the reverse. Testing
the fast path against an input the framework rules out proves less than it
appears to.

Swapping the other way exercises the same thing -- a child differing only in
nullability keeps the projection mapping identical, since
`ProjectionMapping::try_new` reads only field names and indices -- while
staying inside what a rule is allowed to do.

Worth recording why the cached output schema is not a hazard here. Both
`replace_children` paths carry the existing `Projector` over, so the output
schema does not track a child whose nullability changed. Since a rule may only
tighten, that cached schema can only ever be more conservative than the child,
never less, so it cannot claim non-null for data that carries nulls.
@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

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

Comparing qizhu/reuse-eq-group-on-child-swap (09d9cd2) to c429919 (merge-base) diff

Run configuration
run benchmark sql_planner
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

group                                                 HEAD                                   qizhu_reuse-eq-group-on-child-swap
-----                                                 ----                                   ----------------------------------
logical_aggregate_with_join                           1.00    456.3±1.34µs        ? ?/sec    1.00    455.8±1.31µs        ? ?/sec
logical_correlated_subquery_exists                    1.00    286.6±0.80µs        ? ?/sec    1.00    286.1±1.12µs        ? ?/sec
logical_correlated_subquery_in                        1.00    288.4±0.53µs        ? ?/sec    1.00    287.8±1.14µs        ? ?/sec
logical_distinct_many_columns                         1.00    574.9±2.73µs        ? ?/sec    1.00    576.0±3.38µs        ? ?/sec
logical_join_4_with_agg_and_filter                    1.01    256.4±1.26µs        ? ?/sec    1.00    253.8±1.52µs        ? ?/sec
logical_join_8_with_agg_sort_limit                    1.00    427.1±1.45µs        ? ?/sec    1.00    426.9±2.41µs        ? ?/sec
logical_join_chain_16                                 1.00    673.5±3.77µs        ? ?/sec    1.00    675.6±3.54µs        ? ?/sec
logical_join_chain_4                                  1.00    123.5±0.41µs        ? ?/sec    1.00    123.0±0.77µs        ? ?/sec
logical_join_chain_8                                  1.00    250.1±0.80µs        ? ?/sec    1.00    251.3±1.26µs        ? ?/sec
logical_multiple_subqueries                           1.00    526.4±1.28µs        ? ?/sec    1.00    524.9±3.61µs        ? ?/sec
logical_nested_cte_4_levels                           1.05    274.0±1.52µs        ? ?/sec    1.00    261.2±1.00µs        ? ?/sec
logical_plan_struct_join_agg_sort                     1.04    189.4±0.94µs        ? ?/sec    1.00    182.8±0.93µs        ? ?/sec
logical_plan_tpcds_all                                1.00     95.2±0.17ms        ? ?/sec    1.00     95.1±0.92ms        ? ?/sec
logical_plan_tpch_all                                 1.01      6.8±0.03ms        ? ?/sec    1.00      6.7±0.02ms        ? ?/sec
logical_scalar_subquery                               1.00    313.4±1.19µs        ? ?/sec    1.00    312.1±2.06µs        ? ?/sec
logical_select_all_from_1000                          1.02    107.0±1.72ms        ? ?/sec    1.00    104.8±0.21ms        ? ?/sec
logical_select_one_from_700                           1.00    326.2±1.63µs        ? ?/sec    1.00    326.9±2.06µs        ? ?/sec
logical_trivial_join_high_numbered_columns            1.01    287.5±0.76µs        ? ?/sec    1.00    285.3±0.70µs        ? ?/sec
logical_trivial_join_low_numbered_columns             1.01    274.8±1.08µs        ? ?/sec    1.00    272.5±0.53µs        ? ?/sec
logical_union_4_branches                              1.02    428.5±2.55µs        ? ?/sec    1.00    420.2±1.14µs        ? ?/sec
logical_union_8_branches                              1.02    823.1±7.11µs        ? ?/sec    1.00    807.0±3.73µs        ? ?/sec
logical_wide_aggregate_100_exprs                      1.00      4.5±0.01ms        ? ?/sec    1.02      4.6±0.02ms        ? ?/sec
logical_wide_case_50_exprs                            1.00      2.4±0.00ms        ? ?/sec    1.03      2.5±0.02ms        ? ?/sec
logical_wide_filter_200_predicates                    1.00   1324.2±7.37µs        ? ?/sec    1.01   1334.6±9.36µs        ? ?/sec
logical_wide_filter_50_predicates                     1.00    396.4±2.63µs        ? ?/sec    1.00    395.4±2.50µs        ? ?/sec
optimizer_correlated_exists                           1.01    246.7±0.75µs        ? ?/sec    1.00    245.3±0.52µs        ? ?/sec
optimizer_join_4_with_agg_filter                      1.02    466.6±1.86µs        ? ?/sec    1.00    457.2±1.20µs        ? ?/sec
optimizer_join_chain_4                                1.01    182.8±0.60µs        ? ?/sec    1.00    181.5±0.53µs        ? ?/sec
optimizer_join_chain_8                                1.01    567.4±0.90µs        ? ?/sec    1.00    562.6±1.53µs        ? ?/sec
optimizer_select_all_from_1000                        1.00      6.9±0.01ms        ? ?/sec    1.00      6.8±0.02ms        ? ?/sec
optimizer_select_one_from_700                         1.00    257.0±0.63µs        ? ?/sec    1.00    258.1±0.69µs        ? ?/sec
optimizer_tpcds_all                                   1.00    312.5±0.38ms        ? ?/sec    1.00    313.0±0.30ms        ? ?/sec
optimizer_tpch_all                                    1.00     17.5±0.04ms        ? ?/sec    1.00     17.5±0.03ms        ? ?/sec
optimizer_wide_aggregate_100                          1.01      2.3±0.01ms        ? ?/sec    1.00      2.3±0.00ms        ? ?/sec
optimizer_wide_filter_200                             1.00      3.7±0.01ms        ? ?/sec    1.00      3.7±0.01ms        ? ?/sec
physical_intersection                                 1.01    606.7±2.52µs        ? ?/sec    1.00    598.1±2.55µs        ? ?/sec
physical_join_consider_sort                           1.02   1075.5±3.54µs        ? ?/sec    1.00   1051.6±2.47µs        ? ?/sec
physical_join_distinct                                1.01    266.8±0.61µs        ? ?/sec    1.00    264.7±0.71µs        ? ?/sec
physical_many_self_joins                              1.02      7.9±0.02ms        ? ?/sec    1.00      7.7±0.03ms        ? ?/sec
physical_plan_clickbench_all                          1.00    130.0±0.55ms        ? ?/sec    1.22    158.5±3.09ms        ? ?/sec
physical_plan_clickbench_q1                           1.01   1430.5±8.52µs        ? ?/sec    1.00  1422.8±19.54µs        ? ?/sec
physical_plan_clickbench_q10                          1.00      2.1±0.01ms        ? ?/sec    1.27      2.7±0.15ms        ? ?/sec
physical_plan_clickbench_q11                          1.00      2.3±0.01ms        ? ?/sec    1.23      2.8±0.09ms        ? ?/sec
physical_plan_clickbench_q12                          1.00      2.3±0.01ms        ? ?/sec    1.22      2.9±0.10ms        ? ?/sec
physical_plan_clickbench_q13                          1.00      2.1±0.02ms        ? ?/sec    1.23      2.6±0.10ms        ? ?/sec
physical_plan_clickbench_q14                          1.00      2.2±0.01ms        ? ?/sec    1.25      2.8±0.10ms        ? ?/sec
physical_plan_clickbench_q15                          1.00      2.2±0.01ms        ? ?/sec    1.25      2.7±0.08ms        ? ?/sec
physical_plan_clickbench_q16                          1.00   1838.1±8.37µs        ? ?/sec    1.27      2.3±0.09ms        ? ?/sec
physical_plan_clickbench_q17                          1.00   1888.8±7.27µs        ? ?/sec    1.27      2.4±0.08ms        ? ?/sec
physical_plan_clickbench_q18                          1.00   1714.4±7.25µs        ? ?/sec    1.25      2.1±0.08ms        ? ?/sec
physical_plan_clickbench_q19                          1.00      2.1±0.01ms        ? ?/sec    1.27      2.7±0.08ms        ? ?/sec
physical_plan_clickbench_q2                           1.01   1816.4±7.42µs        ? ?/sec    1.00  1803.6±17.70µs        ? ?/sec
physical_plan_clickbench_q20                          1.00   1566.5±7.58µs        ? ?/sec    1.25  1953.5±86.24µs        ? ?/sec
physical_plan_clickbench_q21                          1.00   1811.6±8.08µs        ? ?/sec    1.29      2.3±0.09ms        ? ?/sec
physical_plan_clickbench_q22                          1.00      2.2±0.01ms        ? ?/sec    1.28      2.8±0.08ms        ? ?/sec
physical_plan_clickbench_q23                          1.00      2.4±0.01ms        ? ?/sec    1.26      3.0±0.06ms        ? ?/sec
physical_plan_clickbench_q24                          1.00      6.8±0.02ms        ? ?/sec    1.09      7.4±0.07ms        ? ?/sec
physical_plan_clickbench_q25                          1.00   1941.1±6.52µs        ? ?/sec    1.27      2.5±0.07ms        ? ?/sec
physical_plan_clickbench_q26                          1.00  1775.9±18.27µs        ? ?/sec    1.27      2.3±0.09ms        ? ?/sec
physical_plan_clickbench_q27                          1.00   1968.7±9.38µs        ? ?/sec    1.26      2.5±0.08ms        ? ?/sec
physical_plan_clickbench_q28                          1.00      2.4±0.01ms        ? ?/sec    1.28      3.0±0.08ms        ? ?/sec
physical_plan_clickbench_q29                          1.00      2.5±0.01ms        ? ?/sec    1.27      3.2±0.08ms        ? ?/sec
physical_plan_clickbench_q3                           1.00   1695.1±7.79µs        ? ?/sec    1.00  1696.4±22.73µs        ? ?/sec
physical_plan_clickbench_q30                          1.00     15.8±0.07ms        ? ?/sec    1.02     16.2±0.10ms        ? ?/sec
physical_plan_clickbench_q31                          1.00      2.5±0.01ms        ? ?/sec    1.24      3.1±0.08ms        ? ?/sec
physical_plan_clickbench_q32                          1.00      2.5±0.01ms        ? ?/sec    1.26      3.2±0.07ms        ? ?/sec
physical_plan_clickbench_q33                          1.00      2.1±0.01ms        ? ?/sec    1.26      2.7±0.09ms        ? ?/sec
physical_plan_clickbench_q34                          1.00   1861.0±7.57µs        ? ?/sec    1.28      2.4±0.07ms        ? ?/sec
physical_plan_clickbench_q35                          1.00   1869.9±6.75µs        ? ?/sec    1.31      2.4±0.11ms        ? ?/sec
physical_plan_clickbench_q36                          1.00      2.2±0.01ms        ? ?/sec    1.30      2.8±0.07ms        ? ?/sec
physical_plan_clickbench_q37                          1.00      2.6±0.01ms        ? ?/sec    1.28      3.3±0.08ms        ? ?/sec
physical_plan_clickbench_q38                          1.00      2.6±0.01ms        ? ?/sec    1.28      3.3±0.08ms        ? ?/sec
physical_plan_clickbench_q39                          1.00      2.7±0.01ms        ? ?/sec    1.28      3.4±0.13ms        ? ?/sec
physical_plan_clickbench_q4                           1.00  1514.4±10.96µs        ? ?/sec    1.00  1508.6±35.52µs        ? ?/sec
physical_plan_clickbench_q40                          1.00      3.4±0.01ms        ? ?/sec    1.23      4.1±0.07ms        ? ?/sec
physical_plan_clickbench_q41                          1.00      2.9±0.01ms        ? ?/sec    1.23      3.6±0.07ms        ? ?/sec
physical_plan_clickbench_q42                          1.00      3.1±0.01ms        ? ?/sec    1.23      3.8±0.07ms        ? ?/sec
physical_plan_clickbench_q43                          1.00      3.2±0.01ms        ? ?/sec    1.23      4.0±0.07ms        ? ?/sec
physical_plan_clickbench_q44                          1.00   1624.6±6.35µs        ? ?/sec    1.24      2.0±0.08ms        ? ?/sec
physical_plan_clickbench_q45                          1.00   1629.3±6.65µs        ? ?/sec    1.24      2.0±0.07ms        ? ?/sec
physical_plan_clickbench_q46                          1.00   1953.3±8.23µs        ? ?/sec    1.26      2.5±0.08ms        ? ?/sec
physical_plan_clickbench_q47                          1.00      2.6±0.01ms        ? ?/sec    1.25      3.3±0.08ms        ? ?/sec
physical_plan_clickbench_q48                          1.00      2.8±0.01ms        ? ?/sec    1.23      3.5±0.06ms        ? ?/sec
physical_plan_clickbench_q49                          1.00      2.9±0.01ms        ? ?/sec    1.23      3.5±0.06ms        ? ?/sec
physical_plan_clickbench_q5                           1.00   1654.3±6.41µs        ? ?/sec    1.16  1915.1±124.58µs        ? ?/sec
physical_plan_clickbench_q50                          1.00      2.7±0.01ms        ? ?/sec    1.25      3.4±0.06ms        ? ?/sec
physical_plan_clickbench_q51                          1.00      2.1±0.01ms        ? ?/sec    1.25      2.6±0.11ms        ? ?/sec
physical_plan_clickbench_q6                           1.00   1652.1±7.85µs        ? ?/sec    1.08  1786.6±55.49µs        ? ?/sec
physical_plan_clickbench_q7                           1.00   1471.6±8.24µs        ? ?/sec    1.07  1575.1±41.72µs        ? ?/sec
physical_plan_clickbench_q8                           1.00  1966.7±21.79µs        ? ?/sec    1.11      2.2±0.08ms        ? ?/sec
physical_plan_clickbench_q9                           1.00   1972.3±9.23µs        ? ?/sec    1.08      2.1±0.07ms        ? ?/sec
physical_plan_struct_join_agg_sort                    1.02  1360.3±39.05µs        ? ?/sec    1.00   1329.9±9.33µs        ? ?/sec
physical_plan_tpcds_all                               1.06    759.7±8.58ms        ? ?/sec    1.00    714.9±6.47ms        ? ?/sec
physical_plan_tpch_all                                1.07     47.8±0.29ms        ? ?/sec    1.00     44.6±0.11ms        ? ?/sec
physical_plan_tpch_q1                                 1.01   1609.1±8.21µs        ? ?/sec    1.00   1585.9±3.94µs        ? ?/sec
physical_plan_tpch_q10                                1.06      3.0±0.04ms        ? ?/sec    1.00      2.8±0.02ms        ? ?/sec
physical_plan_tpch_q11                                1.03      2.4±0.04ms        ? ?/sec    1.00      2.3±0.02ms        ? ?/sec
physical_plan_tpch_q12                                1.01  1290.0±10.12µs        ? ?/sec    1.00   1274.6±2.23µs        ? ?/sec
physical_plan_tpch_q13                                1.01   1072.2±8.00µs        ? ?/sec    1.00   1060.6±2.75µs        ? ?/sec
physical_plan_tpch_q14                                1.04  1493.7±46.23µs        ? ?/sec    1.00   1433.6±3.77µs        ? ?/sec
physical_plan_tpch_q16                                1.01  1653.7±13.31µs        ? ?/sec    1.00   1635.6±3.75µs        ? ?/sec
physical_plan_tpch_q17                                1.03  1702.0±10.75µs        ? ?/sec    1.00   1658.9±5.37µs        ? ?/sec
physical_plan_tpch_q18                                1.02      2.0±0.02ms        ? ?/sec    1.00   1978.8±3.71µs        ? ?/sec
physical_plan_tpch_q19                                1.01  1937.7±11.24µs        ? ?/sec    1.00   1911.4±2.97µs        ? ?/sec
physical_plan_tpch_q2                                 1.08      3.9±0.10ms        ? ?/sec    1.00      3.6±0.01ms        ? ?/sec
physical_plan_tpch_q20                                1.05      2.3±0.04ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_tpch_q21                                1.03      2.9±0.03ms        ? ?/sec    1.00      2.8±0.02ms        ? ?/sec
physical_plan_tpch_q22                                1.02  1545.3±11.21µs        ? ?/sec    1.00   1510.4±5.30µs        ? ?/sec
physical_plan_tpch_q3                                 1.04  1942.0±18.60µs        ? ?/sec    1.00   1873.1±4.44µs        ? ?/sec
physical_plan_tpch_q4                                 1.02   1240.3±6.13µs        ? ?/sec    1.00   1218.0±2.76µs        ? ?/sec
physical_plan_tpch_q5                                 1.05      2.9±0.03ms        ? ?/sec    1.00      2.8±0.00ms        ? ?/sec
physical_plan_tpch_q6                                 1.01    644.6±2.80µs        ? ?/sec    1.00    636.2±2.39µs        ? ?/sec
physical_plan_tpch_q7                                 1.06      3.0±0.06ms        ? ?/sec    1.00      2.8±0.00ms        ? ?/sec
physical_plan_tpch_q8                                 1.09      4.2±0.03ms        ? ?/sec    1.00      3.9±0.01ms        ? ?/sec
physical_plan_tpch_q9                                 1.08      2.9±0.03ms        ? ?/sec    1.00      2.7±0.00ms        ? ?/sec
physical_select_aggregates_from_200                   1.01     15.8±0.03ms        ? ?/sec    1.00     15.6±0.06ms        ? ?/sec
physical_select_all_from_1000                         1.00    116.3±0.44ms        ? ?/sec    1.02    118.4±1.86ms        ? ?/sec
physical_select_one_from_700                          1.00    771.9±2.47µs        ? ?/sec    1.00    770.1±3.15µs        ? ?/sec
physical_sorted_union_order_by_10_int64               1.05      4.4±0.03ms        ? ?/sec    1.00      4.2±0.01ms        ? ?/sec
physical_sorted_union_order_by_10_uint64              1.08      9.4±0.03ms        ? ?/sec    1.00      8.7±0.02ms        ? ?/sec
physical_sorted_union_order_by_50_int64               1.04     99.1±0.43ms        ? ?/sec    1.00     95.4±0.30ms        ? ?/sec
physical_sorted_union_order_by_50_uint64              1.13    416.0±1.48ms        ? ?/sec    1.00    369.8±1.17ms        ? ?/sec
physical_theta_join_consider_sort                     1.00   1081.7±4.51µs        ? ?/sec    1.00   1080.0±3.34µs        ? ?/sec
physical_unnest_to_join                               1.00    637.6±1.88µs        ? ?/sec    1.00    638.0±2.16µs        ? ?/sec
physical_window_function_partition_by_12_on_values    1.01    729.9±1.64µs        ? ?/sec    1.00    721.8±1.74µs        ? ?/sec
physical_window_function_partition_by_30_on_values    1.02   1436.8±3.68µs        ? ?/sec    1.00   1413.1±4.37µs        ? ?/sec
physical_window_function_partition_by_4_on_values     1.01    450.8±1.56µs        ? ?/sec    1.00    444.5±1.36µs        ? ?/sec
physical_window_function_partition_by_7_on_values     1.01    551.9±1.51µs        ? ?/sec    1.00    545.5±1.79µs        ? ?/sec
physical_window_function_partition_by_8_on_values     1.00    592.1±1.88µs        ? ?/sec    1.00    594.9±2.17µs        ? ?/sec
with_param_values_many_columns                        1.00    436.7±2.34µs        ? ?/sec    1.00    437.8±3.03µs        ? ?/sec

Resource Usage

sql_planner — base (merge-base)

Metric Value
Wall time 2580.6s
Peak memory 132.0 MiB
Avg memory 63.4 MiB
CPU user 1903.4s
CPU sys 1.6s
Peak spill 0 B

sql_planner — branch

Metric Value
Wall time 2470.5s
Peak memory 131.1 MiB
Avg memory 63.2 MiB
CPU user 1843.6s
CPU sys 1.3s
Peak spill 0 B

File an issue against this benchmark runner

…anning

The equivalence-group comparison was changed to set semantics in review. That
turned an O(n) positional comparison into an O(n^2) scan on a hot path --
`ProjectionExec` consults it on every child replacement during physical
optimization -- and the benchmark bot caught it: `physical_plan_clickbench_all`
went from 129.7ms to 158.5ms against an unchanged 130.0ms baseline, with most
clickbench queries 1.22x to 1.31x slower. The run before that change showed no
regression at all.

Measured directly on the comparison, 20k iterations of two equal groups:

     classes   positional   set-wise   ratio
           8      121.9ms    267.5ms    2.2x
          16      204.2ms    899.3ms    4.4x
          32      404.1ms      3.23s    8.0x
          64      807.5ms     12.29s   15.2x

Positional is linear, set-wise quadratic, and the quadratic term costs far more
than the recomputation the fast path exists to avoid.

The review comment behind the change was about API shape rather than
correctness: a public `PartialEq` reads as semantic equality, and a positional
comparison of a `Vec` whose order is incidental is not that. Rather than pay
for set semantics, this drops `PartialEq` and exposes `has_same_classes`, whose
name claims only what it does. The doc records why it is positional and why the
one direction it can err in is harmless: a caller can be told the groups differ
when they match, never the reverse, so it only ever forfeits an optimization.
@zhuqi-lucas

Copy link
Copy Markdown
Contributor Author

run benchmark sql_planner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5339090159-1734-d742x 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 qizhu/reuse-eq-group-on-child-swap (95cc536) to c429919 (merge-base) diff

Run configuration
run benchmark sql_planner

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 qizhu/reuse-eq-group-on-child-swap (95cc536) to c429919 (merge-base) diff

Run configuration
run benchmark sql_planner
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

group                                                 HEAD                                    qizhu_reuse-eq-group-on-child-swap
-----                                                 ----                                    ----------------------------------
logical_aggregate_with_join                           1.00    454.2±2.27µs        ? ?/sec     1.00    454.3±2.16µs        ? ?/sec
logical_correlated_subquery_exists                    1.00    282.6±2.45µs        ? ?/sec     1.00    283.2±0.54µs        ? ?/sec
logical_correlated_subquery_in                        1.00    284.3±1.83µs        ? ?/sec     1.00    284.8±0.61µs        ? ?/sec
logical_distinct_many_columns                         1.00    567.4±1.50µs        ? ?/sec     1.01    571.1±4.18µs        ? ?/sec
logical_join_4_with_agg_and_filter                    1.00    250.9±1.21µs        ? ?/sec     1.02    257.1±1.27µs        ? ?/sec
logical_join_8_with_agg_sort_limit                    1.00    428.4±3.91µs        ? ?/sec     1.02    436.4±4.58µs        ? ?/sec
logical_join_chain_16                                 1.00    672.3±4.68µs        ? ?/sec     1.00    675.6±3.67µs        ? ?/sec
logical_join_chain_4                                  1.00    120.3±0.55µs        ? ?/sec     1.01    121.1±0.44µs        ? ?/sec
logical_join_chain_8                                  1.00    246.9±1.14µs        ? ?/sec     1.01    248.9±1.59µs        ? ?/sec
logical_multiple_subqueries                           1.00    518.6±1.74µs        ? ?/sec     1.02    529.5±6.86µs        ? ?/sec
logical_nested_cte_4_levels                           1.00    262.3±1.86µs        ? ?/sec     1.00    263.4±1.65µs        ? ?/sec
logical_plan_struct_join_agg_sort                     1.03    184.9±0.97µs        ? ?/sec     1.00    180.3±2.24µs        ? ?/sec
logical_plan_tpcds_all                                1.00     94.7±0.92ms        ? ?/sec     1.01     95.2±0.50ms        ? ?/sec
logical_plan_tpch_all                                 1.00      6.7±0.03ms        ? ?/sec     1.01      6.7±0.02ms        ? ?/sec
logical_scalar_subquery                               1.00    306.5±2.54µs        ? ?/sec     1.02    311.7±2.05µs        ? ?/sec
logical_select_all_from_1000                          1.00    104.7±0.43ms        ? ?/sec     1.00    104.4±0.23ms        ? ?/sec
logical_select_one_from_700                           1.00    327.3±7.79µs        ? ?/sec     1.00    325.8±1.80µs        ? ?/sec
logical_trivial_join_high_numbered_columns            1.01    286.4±1.27µs        ? ?/sec     1.00    284.4±1.17µs        ? ?/sec
logical_trivial_join_low_numbered_columns             1.00    271.7±0.58µs        ? ?/sec     1.00    271.9±0.79µs        ? ?/sec
logical_union_4_branches                              1.00    418.9±1.97µs        ? ?/sec     1.02    428.4±2.30µs        ? ?/sec
logical_union_8_branches                              1.00    813.6±9.37µs        ? ?/sec     1.01    822.8±3.30µs        ? ?/sec
logical_wide_aggregate_100_exprs                      1.00      4.5±0.01ms        ? ?/sec     1.02      4.6±0.04ms        ? ?/sec
logical_wide_case_50_exprs                            1.00      2.4±0.02ms        ? ?/sec     1.01      2.4±0.00ms        ? ?/sec
logical_wide_filter_200_predicates                    1.00  1312.2±11.49µs        ? ?/sec     1.00   1309.4±6.97µs        ? ?/sec
logical_wide_filter_50_predicates                     1.00    392.3±2.97µs        ? ?/sec     1.00    392.8±2.99µs        ? ?/sec
optimizer_correlated_exists                           1.00    246.1±1.52µs        ? ?/sec     1.00    246.8±1.66µs        ? ?/sec
optimizer_join_4_with_agg_filter                      1.01    458.6±2.78µs        ? ?/sec     1.00    456.3±1.84µs        ? ?/sec
optimizer_join_chain_4                                1.01    181.8±0.38µs        ? ?/sec     1.00    179.9±0.34µs        ? ?/sec
optimizer_join_chain_8                                1.00    565.1±1.47µs        ? ?/sec     1.00    566.0±2.91µs        ? ?/sec
optimizer_select_all_from_1000                        1.01      6.9±0.04ms        ? ?/sec     1.00      6.8±0.02ms        ? ?/sec
optimizer_select_one_from_700                         1.00    258.5±0.96µs        ? ?/sec     1.00    259.0±1.03µs        ? ?/sec
optimizer_tpcds_all                                   1.01    315.4±5.31ms        ? ?/sec     1.00    312.7±4.40ms        ? ?/sec
optimizer_tpch_all                                    1.02     17.6±0.26ms        ? ?/sec     1.00     17.2±0.11ms        ? ?/sec
optimizer_wide_aggregate_100                          1.00      2.3±0.01ms        ? ?/sec     1.00      2.3±0.00ms        ? ?/sec
optimizer_wide_filter_200                             1.01      3.7±0.05ms        ? ?/sec     1.00      3.7±0.01ms        ? ?/sec
physical_intersection                                 1.02    600.6±3.11µs        ? ?/sec     1.00    588.6±2.28µs        ? ?/sec
physical_join_consider_sort                           1.02   1052.1±2.87µs        ? ?/sec     1.00   1035.7±4.09µs        ? ?/sec
physical_join_distinct                                1.00    265.9±0.55µs        ? ?/sec     1.00    265.0±1.59µs        ? ?/sec
physical_many_self_joins                              1.00      7.7±0.02ms        ? ?/sec     1.00      7.7±0.06ms        ? ?/sec
physical_plan_clickbench_all                          1.00    134.0±8.24ms        ? ?/sec     1.03   137.7±11.67ms        ? ?/sec
physical_plan_clickbench_q1                           1.00  1398.3±10.12µs        ? ?/sec     1.00   1400.3±9.30µs        ? ?/sec
physical_plan_clickbench_q10                          1.01      2.1±0.01ms        ? ?/sec     1.00      2.1±0.05ms        ? ?/sec
physical_plan_clickbench_q11                          1.00      2.2±0.01ms        ? ?/sec     1.00      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q12                          1.00      2.8±0.27ms        ? ?/sec     1.05      2.9±0.03ms        ? ?/sec
physical_plan_clickbench_q13                          1.00      2.1±0.01ms        ? ?/sec     1.04      2.1±0.19ms        ? ?/sec
physical_plan_clickbench_q14                          1.00      2.2±0.01ms        ? ?/sec     1.00      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q15                          1.01      2.2±0.23ms        ? ?/sec     1.00      2.2±0.20ms        ? ?/sec
physical_plan_clickbench_q16                          1.00  1843.2±133.56µs        ? ?/sec    1.00  1844.7±122.32µs        ? ?/sec
physical_plan_clickbench_q17                          1.00   1868.4±9.33µs        ? ?/sec     1.03  1932.3±184.01µs        ? ?/sec
physical_plan_clickbench_q18                          1.21      2.0±0.20ms        ? ?/sec     1.00   1681.4±7.59µs        ? ?/sec
physical_plan_clickbench_q19                          1.08      2.3±0.24ms        ? ?/sec     1.00      2.1±0.05ms        ? ?/sec
physical_plan_clickbench_q2                           1.01      2.0±0.25ms        ? ?/sec     1.00      2.0±0.24ms        ? ?/sec
physical_plan_clickbench_q20                          1.00  1560.3±74.99µs        ? ?/sec     1.02  1590.6±105.04µs        ? ?/sec
physical_plan_clickbench_q21                          1.00   1794.7±8.78µs        ? ?/sec     1.00  1787.8±48.55µs        ? ?/sec
physical_plan_clickbench_q22                          1.01      2.2±0.01ms        ? ?/sec     1.00      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q23                          1.00      2.9±0.26ms        ? ?/sec     1.02      2.9±0.12ms        ? ?/sec
physical_plan_clickbench_q24                          1.01      6.8±0.06ms        ? ?/sec     1.00      6.8±0.27ms        ? ?/sec
physical_plan_clickbench_q25                          1.00  1925.5±19.51µs        ? ?/sec     1.00  1920.6±46.23µs        ? ?/sec
physical_plan_clickbench_q26                          1.02  1782.9±123.40µs        ? ?/sec    1.00   1747.7±7.94µs        ? ?/sec
physical_plan_clickbench_q27                          1.02  1987.3±141.76µs        ? ?/sec    1.00   1940.7±8.02µs        ? ?/sec
physical_plan_clickbench_q28                          1.00      2.5±0.28ms        ? ?/sec     1.02      2.6±0.29ms        ? ?/sec
physical_plan_clickbench_q29                          1.02      2.9±0.34ms        ? ?/sec     1.00      2.8±0.31ms        ? ?/sec
physical_plan_clickbench_q3                           1.00  1741.2±143.93µs        ? ?/sec    1.00  1736.8±132.44µs        ? ?/sec
physical_plan_clickbench_q30                          1.03     16.1±0.24ms        ? ?/sec     1.00     15.6±0.27ms        ? ?/sec
physical_plan_clickbench_q31                          1.00      2.6±0.15ms        ? ?/sec     1.02      2.6±0.23ms        ? ?/sec
physical_plan_clickbench_q32                          1.01      2.5±0.02ms        ? ?/sec     1.00      2.5±0.01ms        ? ?/sec
physical_plan_clickbench_q33                          1.01      2.1±0.01ms        ? ?/sec     1.00      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q34                          1.02      2.0±0.26ms        ? ?/sec     1.00  1979.0±222.37µs        ? ?/sec
physical_plan_clickbench_q35                          1.02  1932.0±110.32µs        ? ?/sec    1.00   1887.0±9.78µs        ? ?/sec
physical_plan_clickbench_q36                          1.01      2.2±0.01ms        ? ?/sec     1.00      2.2±0.01ms        ? ?/sec
physical_plan_clickbench_q37                          1.04      2.7±0.23ms        ? ?/sec     1.00      2.6±0.07ms        ? ?/sec
physical_plan_clickbench_q38                          1.00      2.7±0.26ms        ? ?/sec     1.00      2.7±0.25ms        ? ?/sec
physical_plan_clickbench_q39                          1.01      2.7±0.02ms        ? ?/sec     1.00      2.6±0.01ms        ? ?/sec
physical_plan_clickbench_q4                           1.00  1533.9±104.71µs        ? ?/sec    1.00  1537.4±100.89µs        ? ?/sec
physical_plan_clickbench_q40                          1.02      4.2±0.12ms        ? ?/sec     1.00      4.1±0.10ms        ? ?/sec
physical_plan_clickbench_q41                          1.00      3.0±0.25ms        ? ?/sec     1.02      3.1±0.28ms        ? ?/sec
physical_plan_clickbench_q42                          1.00      3.1±0.02ms        ? ?/sec     1.01      3.1±0.16ms        ? ?/sec
physical_plan_clickbench_q43                          1.05      3.4±0.27ms        ? ?/sec     1.00      3.2±0.12ms        ? ?/sec
physical_plan_clickbench_q44                          1.00   1607.1±8.49µs        ? ?/sec     1.02  1645.6±123.80µs        ? ?/sec
physical_plan_clickbench_q45                          1.00   1580.5±8.57µs        ? ?/sec     1.02   1606.9±7.19µs        ? ?/sec
physical_plan_clickbench_q46                          1.04      2.2±0.25ms        ? ?/sec     1.00      2.2±0.24ms        ? ?/sec
physical_plan_clickbench_q47                          1.00      2.6±0.04ms        ? ?/sec     1.06      2.8±0.24ms        ? ?/sec
physical_plan_clickbench_q48                          1.00      2.9±0.27ms        ? ?/sec     1.01      3.0±0.28ms        ? ?/sec
physical_plan_clickbench_q49                          1.05      3.0±0.26ms        ? ?/sec     1.00      2.8±0.01ms        ? ?/sec
physical_plan_clickbench_q5                           1.02  1666.1±37.55µs        ? ?/sec     1.00   1639.6±9.00µs        ? ?/sec
physical_plan_clickbench_q50                          1.00      2.7±0.02ms        ? ?/sec     1.02      2.8±0.17ms        ? ?/sec
physical_plan_clickbench_q51                          1.24      2.6±0.15ms        ? ?/sec     1.00      2.1±0.13ms        ? ?/sec
physical_plan_clickbench_q6                           1.02  1665.2±10.42µs        ? ?/sec     1.00   1630.6±6.99µs        ? ?/sec
physical_plan_clickbench_q7                           1.00  1681.2±180.35µs        ? ?/sec    1.00  1673.2±154.63µs        ? ?/sec
physical_plan_clickbench_q8                           1.00      2.0±0.18ms        ? ?/sec     1.01      2.1±0.20ms        ? ?/sec
physical_plan_clickbench_q9                           1.00      2.1±0.20ms        ? ?/sec     1.00      2.1±0.16ms        ? ?/sec
physical_plan_struct_join_agg_sort                    1.05  1362.3±54.26µs        ? ?/sec     1.00   1293.8±2.82µs        ? ?/sec
physical_plan_tpcds_all                               1.02   738.8±19.59ms        ? ?/sec     1.00   725.4±17.51ms        ? ?/sec
physical_plan_tpch_all                                1.01     46.0±1.07ms        ? ?/sec     1.00     45.6±1.94ms        ? ?/sec
physical_plan_tpch_q1                                 1.00  1595.5±34.11µs        ? ?/sec     1.00  1595.0±69.56µs        ? ?/sec
physical_plan_tpch_q10                                1.04      3.1±0.15ms        ? ?/sec     1.00      3.0±0.16ms        ? ?/sec
physical_plan_tpch_q11                                1.02      2.3±0.00ms        ? ?/sec     1.00      2.2±0.02ms        ? ?/sec
physical_plan_tpch_q12                                1.00   1285.9±7.09µs        ? ?/sec     1.00   1282.8±8.01µs        ? ?/sec
physical_plan_tpch_q13                                1.00   1064.0±3.79µs        ? ?/sec     1.01  1077.0±31.55µs        ? ?/sec
physical_plan_tpch_q14                                1.05  1474.5±44.59µs        ? ?/sec     1.00  1401.6±45.59µs        ? ?/sec
physical_plan_tpch_q16                                1.04  1673.7±63.51µs        ? ?/sec     1.00  1607.8±10.91µs        ? ?/sec
physical_plan_tpch_q17                                1.00  1690.7±25.52µs        ? ?/sec     1.01  1708.0±80.85µs        ? ?/sec
physical_plan_tpch_q18                                1.01   1987.6±5.34µs        ? ?/sec     1.00  1959.0±19.12µs        ? ?/sec
physical_plan_tpch_q19                                1.02  1941.0±58.96µs        ? ?/sec     1.00  1901.1±58.56µs        ? ?/sec
physical_plan_tpch_q2                                 1.01      3.7±0.17ms        ? ?/sec     1.00      3.7±0.16ms        ? ?/sec
physical_plan_tpch_q20                                1.03      2.3±0.14ms        ? ?/sec     1.00      2.2±0.11ms        ? ?/sec
physical_plan_tpch_q21                                1.01      2.9±0.01ms        ? ?/sec     1.00      2.8±0.01ms        ? ?/sec
physical_plan_tpch_q22                                1.02  1671.8±95.34µs        ? ?/sec     1.00  1642.1±91.43µs        ? ?/sec
physical_plan_tpch_q3                                 1.01  1902.4±31.74µs        ? ?/sec     1.00  1880.0±46.40µs        ? ?/sec
physical_plan_tpch_q4                                 1.01   1223.1±2.59µs        ? ?/sec     1.00   1214.3±2.46µs        ? ?/sec
physical_plan_tpch_q5                                 1.00      3.0±0.15ms        ? ?/sec     1.00      3.0±0.13ms        ? ?/sec
physical_plan_tpch_q6                                 1.02    639.2±5.09µs        ? ?/sec     1.00    626.7±4.59µs        ? ?/sec
physical_plan_tpch_q7                                 1.01      2.9±0.15ms        ? ?/sec     1.00      2.9±0.15ms        ? ?/sec
physical_plan_tpch_q8                                 1.01      3.9±0.01ms        ? ?/sec     1.00      3.9±0.01ms        ? ?/sec
physical_plan_tpch_q9                                 1.02      2.7±0.01ms        ? ?/sec     1.00      2.7±0.01ms        ? ?/sec
physical_select_aggregates_from_200                   1.00     15.7±0.13ms        ? ?/sec     1.00     15.6±0.12ms        ? ?/sec
physical_select_all_from_1000                         1.00    115.9±0.27ms        ? ?/sec     1.00    115.7±0.26ms        ? ?/sec
physical_select_one_from_700                          1.00    763.8±3.27µs        ? ?/sec     1.01    769.9±4.12µs        ? ?/sec
physical_sorted_union_order_by_10_int64               1.00      4.3±0.11ms        ? ?/sec     1.04      4.4±0.02ms        ? ?/sec
physical_sorted_union_order_by_10_uint64              1.05      9.1±0.05ms        ? ?/sec     1.00      8.7±0.10ms        ? ?/sec
physical_sorted_union_order_by_50_int64               1.02     98.5±2.26ms        ? ?/sec     1.00     96.2±1.88ms        ? ?/sec
physical_sorted_union_order_by_50_uint64              1.10    410.3±7.29ms        ? ?/sec     1.00    373.9±8.28ms        ? ?/sec
physical_theta_join_consider_sort                     1.01  1082.0±11.86µs        ? ?/sec     1.00  1073.4±14.80µs        ? ?/sec
physical_unnest_to_join                               1.02    641.8±3.51µs        ? ?/sec     1.00    632.0±8.57µs        ? ?/sec
physical_window_function_partition_by_12_on_values    1.02    724.8±5.20µs        ? ?/sec     1.00    712.6±6.99µs        ? ?/sec
physical_window_function_partition_by_30_on_values    1.02   1428.8±7.52µs        ? ?/sec     1.00   1398.9±5.17µs        ? ?/sec
physical_window_function_partition_by_4_on_values     1.03    439.8±1.58µs        ? ?/sec     1.00    426.2±2.53µs        ? ?/sec
physical_window_function_partition_by_7_on_values     1.03    541.5±2.08µs        ? ?/sec     1.00    525.1±2.50µs        ? ?/sec
physical_window_function_partition_by_8_on_values     1.03    585.0±3.14µs        ? ?/sec     1.00    569.2±4.88µs        ? ?/sec
with_param_values_many_columns                        1.01    437.7±3.70µs        ? ?/sec     1.00    433.7±2.93µs        ? ?/sec

Resource Usage

sql_planner — base (merge-base)

Metric Value
Wall time 2145.5s
Peak memory 130.8 MiB
Avg memory 73.9 MiB
CPU user 1883.2s
CPU sys 1.3s
Peak spill 0 B

sql_planner — branch

Metric Value
Wall time 2335.5s
Peak memory 133.7 MiB
Avg memory 69.9 MiB
CPU user 1874.6s
CPU sys 1.4s
Peak spill 0 B

File an issue against this benchmark runner

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

Labels

physical-expr Changes to the physical-expr crates physical-plan Changes to the physical-plan crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Projections re-project an unchanged equivalence group when a rule inserts a sort below them

4 participants