Skip to content

[fix](eager-agg) Handle duplicate aggregate functions pushed through projects - #66531

Open
feiniaofeiafei wants to merge 4 commits into
apache:masterfrom
feiniaofeiafei:eager_agg_use_identify_map_master
Open

[fix](eager-agg) Handle duplicate aggregate functions pushed through projects#66531
feiniaofeiafei wants to merge 4 commits into
apache:masterfrom
feiniaofeiafei:eager_agg_use_identify_map_master

Conversation

@feiniaofeiafei

@feiniaofeiafei feiniaofeiafei commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

What problem does this PR solve?

Related PR: #63690

Problem Summary:

Eager aggregation pushdown may fail when different aggregate functions become
the same expression after passing through a Project. report error:

2026-08-06 04:26:54,285 INFO (mysql-nio-pool-14|325) [PushDownAggregation.visitLogicalAggregate():280] PushDownAggregation failed: Cannot invoke "org.apache.doris.nereids.trees.expressions.NamedExpression.toSlot()" because "namedExpression" is null
        at org.apache.doris.nereids.rules.rewrite.eageraggregation.EagerAggRewriter.visitLogicalProject(EagerAggRewriter.java:718)
        at org.apache.doris.nereids.rules.rewrite.eageraggregation.EagerAggRewriter.visitLogicalProject(EagerAggRewriter.java:90)
        at org.apache.doris.nereids.trees.plans.logical.LogicalProject.accept(LogicalProject.java:160)
        at org.apache.doris.nereids.rules.rewrite.eageraggregation.EagerAggRewriter.visitLogicalUnion(EagerAggRewriter.java:582)
        at org.apache.doris.nereids.rules.rewrite.eageraggregation.EagerAggRewriter.visitLogicalUnion(EagerAggRewriter.java:90)
        at org.apache.doris.nereids.trees.plans.logical.LogicalUnion.accept(LogicalUnion.java:155)

For example:

Aggregate: SUM(x)#4, SUM(y)#5
  Union All
    Project: 0 AS x, 0 AS y
      Join

After pushing the aggregates through the Project, both functions becomeSUM(0):

functions: [SUM(0), SUM(0)]
aliasMap:  SUM(0) -> #5

Because aliasMap uses expression equality, only one entry is retained.
The Project still tries to read both #4 and #5 from BilateralState,
causing a null lookup.

This PR deduplicates the child aggregate and records the ExprId mapping:

child aggregate: SUM(0) -> #8
ExprId mapping:  #4 -> #8, #5 -> #8

The Project then restores both required outputs:

slot#8 AS slot#4
slot#8 AS slot#5

When no aggregate functions are merged, the original ExprIds are reused to
avoid unnecessary aliases.

The same fix also covers cases such as:

Project: a#1 AS x, a#1 AS y

where SUM(x) and SUM(y) both become SUM(a#1) after pushdown.

Release note

None

Check List (For Author)

  • Test

    • Regression test
      • query_p0/eager_agg/bilateral_eager_agg
      • Covers two aggregate functions that become the same function after
        Project pushdown.
    • Unit Test
    • Manual test
    • No need to test or manual test.
  • Behavior changed:

    • Yes.
      • Prevents eager aggregation pushdown from failing when multiple
        aggregate functions become identical after Project rewriting.
      • eager_aggregation_mode=1 can force eligible pushdown after a UNION.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@feiniaofeiafei

Copy link
Copy Markdown
Collaborator Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 2.97% (3/101) 🎉
Increment coverage report
Complete coverage report

@feiniaofeiafei

Copy link
Copy Markdown
Collaborator Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28827 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit b3d4f0d64a87166d3fa65af2c2cf00f5b476f930, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17636	4058	3950	3950
q2	2048	321	210	210
q3	10253	1389	795	795
q4	4679	467	334	334
q5	7542	826	565	565
q6	181	166	135	135
q7	821	804	600	600
q8	9328	1580	1584	1580
q9	5317	4137	4047	4047
q10	6728	1622	1357	1357
q11	504	350	327	327
q12	718	586	451	451
q13	18102	3290	2755	2755
q14	264	263	239	239
q15	q16	736	739	666	666
q17	1004	953	1004	953
q18	6497	5612	5582	5582
q19	1367	1271	1034	1034
q20	791	668	559	559
q21	5885	2563	2387	2387
q22	443	354	301	301
Total cold run time: 100844 ms
Total hot run time: 28827 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4339	4249	4243	4243
q2	269	319	210	210
q3	4625	4892	4393	4393
q4	2169	2259	1410	1410
q5	4212	4103	4131	4103
q6	223	168	131	131
q7	1693	1576	1394	1394
q8	2713	2208	2116	2116
q9	7334	7537	7533	7533
q10	4293	4257	3903	3903
q11	568	423	387	387
q12	732	768	497	497
q13	3162	3502	2891	2891
q14	293	297	276	276
q15	q16	713	715	634	634
q17	1298	1262	1283	1262
q18	12109	11053	11825	11053
q19	1144	1148	1228	1148
q20	2248	2212	1948	1948
q21	5608	4817	4901	4817
q22	543	489	432	432
Total cold run time: 60288 ms
Total hot run time: 54781 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 166510 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit b3d4f0d64a87166d3fa65af2c2cf00f5b476f930, data reload: false

query5	4324	584	446	446
query6	453	228	211	211
query7	4870	560	334	334
query8	321	159	148	148
query9	8773	4022	4012	4012
query10	448	365	287	287
query11	5811	2169	1957	1957
query12	151	100	96	96
query13	1281	570	476	476
query14	6073	4246	3981	3981
query14_1	3788	3758	3787	3758
query15	205	197	175	175
query16	991	477	453	453
query17	950	704	569	569
query18	2488	446	326	326
query19	200	180	146	146
query20	103	99	99	99
query21	231	154	130	130
query22	12951	13018	12808	12808
query23	15776	15096	14567	14567
query23_1	15352	15142	15088	15088
query24	7678	1686	1234	1234
query24_1	1177	1214	1216	1214
query25	510	402	340	340
query26	1324	345	233	233
query27	2592	575	391	391
query28	4550	2002	2023	2002
query29	1041	587	456	456
query30	338	259	217	217
query31	1165	1113	1037	1037
query32	117	59	59	59
query33	508	313	235	235
query34	1185	1114	635	635
query35	714	721	634	634
query36	795	780	709	709
query37	154	107	85	85
query38	1813	1790	1668	1668
query39	815	826	798	798
query39_1	805	773	792	773
query40	243	159	133	133
query41	61	60	61	60
query42	92	88	88	88
query43	314	319	265	265
query44	1412	767	766	766
query45	179	169	158	158
query46	1048	1180	729	729
query47	1555	1573	1448	1448
query48	420	396	316	316
query49	572	398	283	283
query50	1078	416	331	331
query51	10468	10628	10547	10547
query52	85	86	78	78
query53	269	276	196	196
query54	278	226	219	219
query55	75	74	65	65
query56	311	277	289	277
query57	1017	1025	938	938
query58	286	248	250	248
query59	1487	1558	1366	1366
query60	316	266	254	254
query61	145	143	147	143
query62	402	318	263	263
query63	228	188	192	188
query64	2933	1150	977	977
query65	3879	3809	3822	3809
query66	1846	480	365	365
query67	28061	28134	27982	27982
query68	3270	1643	971	971
query69	412	301	274	274
query70	859	792	840	792
query71	386	358	319	319
query72	3219	2573	2225	2225
query73	849	821	431	431
query74	4615	4474	4278	4278
query75	2383	2334	1979	1979
query76	2340	1140	731	731
query77	330	355	268	268
query78	11219	11058	10489	10489
query79	1355	1108	740	740
query80	834	544	448	448
query81	481	329	284	284
query82	626	175	132	132
query83	376	320	287	287
query84	317	157	128	128
query85	967	616	516	516
query86	360	227	218	218
query87	1958	1974	1821	1821
query88	3671	2789	2789	2789
query89	398	330	281	281
query90	1861	196	187	187
query91	198	185	164	164
query92	60	58	53	53
query93	1672	1615	1027	1027
query94	614	365	309	309
query95	775	582	461	461
query96	1005	827	355	355
query97	2459	2483	2351	2351
query98	191	186	175	175
query99	744	729	618	618
Total cold run time: 252793 ms
Total hot run time: 166510 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.7 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit b3d4f0d64a87166d3fa65af2c2cf00f5b476f930, data reload: false

query1	0.00	0.00	0.00
query2	0.09	0.04	0.05
query3	0.26	0.13	0.13
query4	1.60	0.14	0.14
query5	0.24	0.21	0.22
query6	1.16	0.84	0.80
query7	0.03	0.01	0.01
query8	0.05	0.03	0.04
query9	0.36	0.30	0.32
query10	0.54	0.57	0.56
query11	0.19	0.14	0.13
query12	0.18	0.15	0.14
query13	0.47	0.45	0.47
query14	1.02	0.99	0.98
query15	0.61	0.58	0.59
query16	0.31	0.32	0.31
query17	1.07	1.06	1.08
query18	0.21	0.20	0.19
query19	2.04	1.99	1.93
query20	0.01	0.02	0.02
query21	15.41	0.19	0.13
query22	4.99	0.06	0.05
query23	16.16	0.31	0.12
query24	2.90	0.40	0.33
query25	0.11	0.05	0.04
query26	0.73	0.20	0.16
query27	0.05	0.03	0.04
query28	3.52	0.81	0.36
query29	12.49	4.03	3.16
query30	0.27	0.15	0.15
query31	2.77	0.56	0.31
query32	3.22	0.58	0.50
query33	3.11	3.12	3.16
query34	15.51	3.89	3.28
query35	3.21	3.21	3.19
query36	0.56	0.43	0.44
query37	0.09	0.07	0.06
query38	0.06	0.03	0.03
query39	0.03	0.03	0.03
query40	0.17	0.15	0.13
query41	0.09	0.03	0.02
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 95.97 s
Total hot run time: 23.7 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 12.50% (43/344) 🎉
Increment coverage report
Complete coverage report

@feiniaofeiafei feiniaofeiafei changed the title [fix](eager-agg) Preserve identical aggregate functions in eager aggregation [fix](eager-agg) Handle duplicate aggregate functions pushed through projects Aug 7, 2026
}
boolean needDifferentExprId = aggFunctions.size() != context.getAliasMap().size();

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.

这一轮遍历可以省略, 判断去重可以在 L429 这个 for 循环里一次完成

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants