Skip to content

[opt](nereids) rewrite element_at(split_by_string(s,sep),n) to split_part - #66181

Open
Baymine wants to merge 1 commit into
apache:masterfrom
Baymine:improvement/element-at-split-part
Open

[opt](nereids) rewrite element_at(split_by_string(s,sep),n) to split_part#66181
Baymine wants to merge 1 commit into
apache:masterfrom
Baymine:improvement/element-at-split-part

Conversation

@Baymine

@Baymine Baymine commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #66179

Related PR: N/A

Problem Summary:

element_at(split_by_string(s, d), n) builds the whole split array (a PODArray allocation and a memcpy per part, per row) and then picks a single entry. This rewrites it to split_part(s, d, n), which short-circuits as soon as it locates the n-th delimiter, eliminating the intermediate array and the trailing-parts work.

The rewrite is semantics-preserving. The two forms differ only when the string yields no n-th part: element_at returns NULL while split_part can return ''. To neutralize this, the rule only rewrites the ROOT of a top-level filter conjunct (where NULL and false both drop the row) and is guarded to:

  • EqualTo / InPredicate with a NON-EMPTY string-literal RHS (or an IN-list of non-empty string literals), so a comparison against '' yields false, not true;
  • a NON-EMPTY string-literal separator (an empty/column separator diverges);
  • a NON-NEGATIVE int-literal index (negative back-counting uses rfind and can land on a different boundary for self-overlapping multi-char separators).

It deliberately does NOT recurse into NOT / OR / CASE, where NULL and '' are no longer interchangeable.

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Please explain why:
  • Behavior changed:

  • Does this need documentation?

Check List (For Reviewer who merge this PR)

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

### What problem does this PR solve?

Issue Number: close apache#66179

Problem Summary:
`element_at(split_by_string(s, d), n)` builds the whole split array (a PODArray
allocation and a memcpy per part, per row) and then picks a single entry. This
rewrites it to `split_part(s, d, n)`, which short-circuits as soon as it locates
the n-th delimiter, eliminating the intermediate array and the trailing-parts
work.

The rewrite is semantics-preserving. The two forms differ only when the string
yields no n-th part: `element_at` returns NULL while `split_part` can return ''.
To neutralize this, the rule only rewrites the ROOT of a top-level filter
conjunct (where NULL and false both drop the row) and is guarded to:
- EqualTo / InPredicate with a NON-EMPTY string-literal RHS (or an IN-list of
  non-empty string literals), so a comparison against '' yields false, not true;
- a NON-EMPTY string-literal separator (an empty/column separator diverges);
- a NON-NEGATIVE int-literal index (negative back-counting uses rfind and can
  land on a different boundary for self-overlapping multi-char separators).
It deliberately does NOT recurse into NOT / OR / CASE, where NULL and '' are no
longer interchangeable.

### Release note

None

### Check List (For Author)

- Test <!-- At least one of them must be included. -->
    - [ ] Regression test
    - [x] Unit Test
    - [ ] Manual test (add detailed scripts or steps below)
    - [ ] No need to test or manual test. Explain why:

- Behavior changed:
    - [x] No.
    - [ ] Yes.

- Does this need documentation?
    - [x] No.
    - [ ] Yes.
@Baymine

Baymine commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

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

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17634	4126	4117	4117
q2	2038	324	197	197
q3	10284	1387	827	827
q4	4716	485	339	339
q5	7686	863	552	552
q6	208	183	146	146
q7	784	831	619	619
q8	10096	1570	1604	1570
q9	6219	4365	4336	4336
q10	6843	1736	1451	1451
q11	523	357	340	340
q12	773	613	479	479
q13	18110	3285	2746	2746
q14	267	264	242	242
q15	q16	786	772	706	706
q17	1056	962	1012	962
q18	6869	5670	5621	5621
q19	1845	1300	1110	1110
q20	813	681	587	587
q21	5808	2621	2380	2380
q22	425	369	304	304
Total cold run time: 103783 ms
Total hot run time: 29631 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4486	4332	4436	4332
q2	298	340	220	220
q3	4580	4919	4389	4389
q4	2156	2271	1419	1419
q5	4497	4429	4401	4401
q6	230	184	134	134
q7	2394	1911	1685	1685
q8	2741	2291	2306	2291
q9	7843	7844	7855	7844
q10	4657	4628	4234	4234
q11	743	457	414	414
q12	752	802	548	548
q13	3169	3560	3041	3041
q14	310	317	319	317
q15	q16	724	752	702	702
q17	1413	1366	1390	1366
q18	8165	7482	6924	6924
q19	1155	1101	1100	1100
q20	2215	2216	1947	1947
q21	5445	4833	4647	4647
q22	510	466	402	402
Total cold run time: 58483 ms
Total hot run time: 52357 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 177840 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 bb90ea6977931285b11d05b4a85885d7944d5007, data reload: false

query5	4320	613	496	496
query6	467	227	195	195
query7	4858	585	347	347
query8	337	199	182	182
query9	8785	4134	4109	4109
query10	464	367	299	299
query11	5943	2337	2125	2125
query12	157	107	106	106
query13	1271	626	437	437
query14	6244	5351	5001	5001
query14_1	4376	4380	4378	4378
query15	224	204	178	178
query16	1032	471	453	453
query17	1126	715	588	588
query18	2508	482	345	345
query19	213	195	154	154
query20	115	106	107	106
query21	239	159	139	139
query22	13584	13679	13376	13376
query23	17355	16465	16130	16130
query23_1	16276	16316	16384	16316
query24	7536	1774	1282	1282
query24_1	1317	1310	1286	1286
query25	578	489	345	345
query26	1319	360	219	219
query27	2641	599	377	377
query28	4417	1981	2015	1981
query29	1061	630	453	453
query30	337	262	221	221
query31	1108	1080	989	989
query32	107	61	59	59
query33	517	311	246	246
query34	1167	1137	651	651
query35	760	789	659	659
query36	1028	996	887	887
query37	159	104	99	99
query38	1881	1708	1676	1676
query39	882	868	849	849
query39_1	824	822	824	822
query40	247	165	140	140
query41	64	63	62	62
query42	90	90	90	90
query43	333	331	292	292
query44	1452	785	750	750
query45	193	186	180	180
query46	1087	1221	727	727
query47	2128	2142	1998	1998
query48	405	419	296	296
query49	581	442	310	310
query50	1101	418	367	367
query51	10859	10746	10639	10639
query52	90	87	75	75
query53	267	283	205	205
query54	276	236	214	214
query55	75	70	67	67
query56	309	297	296	296
query57	1319	1247	1208	1208
query58	288	254	269	254
query59	1596	1625	1448	1448
query60	309	271	264	264
query61	150	148	150	148
query62	536	501	429	429
query63	234	201	201	201
query64	2832	1046	866	866
query65	4730	4614	4621	4614
query66	1810	491	385	385
query67	29174	29188	29031	29031
query68	3171	1526	1013	1013
query69	408	314	257	257
query70	900	857	847	847
query71	370	341	329	329
query72	3074	2644	2360	2360
query73	839	772	443	443
query74	5057	4896	4710	4710
query75	2512	2518	2134	2134
query76	2351	1183	779	779
query77	344	383	288	288
query78	11819	11874	11331	11331
query79	1337	1144	791	791
query80	702	571	473	473
query81	483	335	299	299
query82	583	158	119	119
query83	373	335	306	306
query84	284	159	131	131
query85	957	613	530	530
query86	365	244	239	239
query87	1839	1838	1781	1781
query88	3667	2798	2779	2779
query89	443	373	328	328
query90	1866	193	202	193
query91	201	192	159	159
query92	60	60	56	56
query93	1675	1563	968	968
query94	574	367	292	292
query95	784	590	467	467
query96	1085	790	357	357
query97	2635	2617	2489	2489
query98	212	208	213	208
query99	1089	1118	993	993
Total cold run time: 262496 ms
Total hot run time: 177840 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.12	0.05	0.05
query3	0.25	0.14	0.14
query4	1.60	0.14	0.14
query5	0.23	0.23	0.23
query6	1.23	1.06	1.09
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.39	0.32	0.30
query10	0.54	0.54	0.54
query11	0.20	0.13	0.14
query12	0.18	0.15	0.15
query13	0.46	0.47	0.48
query14	1.01	1.01	1.02
query15	0.61	0.60	0.59
query16	0.30	0.32	0.31
query17	1.08	1.15	1.12
query18	0.22	0.20	0.20
query19	2.10	1.91	1.89
query20	0.02	0.01	0.02
query21	15.40	0.20	0.12
query22	4.87	0.05	0.05
query23	16.13	0.32	0.12
query24	2.99	0.43	0.32
query25	0.12	0.06	0.04
query26	0.73	0.20	0.14
query27	0.05	0.04	0.03
query28	3.55	0.92	0.53
query29	12.53	4.13	3.26
query30	0.27	0.15	0.14
query31	2.77	0.61	0.31
query32	3.22	0.60	0.48
query33	3.24	3.22	3.25
query34	15.70	4.20	3.48
query35	3.53	3.55	3.49
query36	0.55	0.43	0.44
query37	0.09	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.18	0.16
query41	0.08	0.03	0.03
query42	0.04	0.03	0.02
query43	0.05	0.04	0.03
Total cold run time: 96.82 s
Total hot run time: 24.91 s

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.

[Enhancement] Rewrite element_at(split_by_string(s,sep),n) to split_part in filter conjuncts

2 participants