Skip to content

[feature](load) Support Stream Load format=arrow into VARIANT columns - #69767

Open
matanper wants to merge 7 commits into
apache:masterfrom
matanper:variant-arrow-load-68890
Open

matanper wants to merge 7 commits into
apache:masterfrom
matanper:variant-arrow-load-68890

Conversation

@matanper

@matanper matanper commented Oct 28, 2026 •

Copy link
Copy Markdown

What problem does this PR solve?

Issue Number: close #68890

Related PR: #68883

Problem Summary:

Stream Load with format=arrow could not load JSON text into a VARIANT
column, and loaded the Parquet Variant binary forms slowly.
DataTypeVariantV2SerDe::read_column_from_arrow accepted only the exact
shape Doris writes for Arrow Flight, struct<metadata: binary, value: binary>
in that field order. Through Stream Load:

  • JSON text, one document per row (utf8, large_utf8, binary,
    large_binary), failed;
  • a struct with the two fields in the other order (pyarrow builds the struct
    by name) failed;
  • large_binary children and a dictionary-encoded metadata child loaded,
    but only because FileScannerV2's Arrow stream reader first normalized them
    to plain binary (normalize_arrow_array).

That normalization is what makes dictionary metadata expensive. A producer
that encodes a record batch at a time has one metadata blob per batch, which
holds every key of the batch, so it grows with the number of distinct keys
and can be far larger than a row's value bytes. As a plain binary child, that
blob is repeated in every row. As dictionary<int32, binary> with one entry
it costs a few bytes per row on the wire, but the reader decoded it back into
a per-row copy, and the SerDe then validated every row's copy of the
metadata.

This PR:

  1. Extends the VARIANT V2 Arrow reader to accept, with or without the
    arrow.parquet.variant extension:
    • JSON text in utf8/large_utf8/binary/large_binary, parsed like
      the Variant column of a JSON load (serde_json_options(): text that is
      not JSON is kept as a string). A NULL row is JSON null.
    • struct<metadata, value> in either field order with binary or
      large_binary children. Rows go through
      ColumnVariantV2::EncodedRowsAppender, which validates every row before
      appending and keeps a batch that shares one metadata blob in the
      single-metadata form. Before, each row was copied into a
      VariantBatchBuilder and then copied again into the column.
    • the same struct with dictionary<integer, binary | large_binary>
      metadata. It maps directly onto ColumnVariantV2::insert_encoded_rows:
      dictionary entries are the metadata blobs and indices are the metadata
      ids. When every row uses one entry, only that entry is passed, so no
      row's metadata is copied, hashed or compared.
      Every shape runs ValidateFull() on the slice and Variant metadata/payload
      validation before the destination changes, so a bad batch appends
      nothing; empty values and empty or NULL dictionary entries are rejected
      with INVALID_ARGUMENT. NULL struct rows become Variant null.
  2. Adds DataTypeVariantV2SerDe::is_arrow_input_type. The FileScannerV2
    Arrow stream reader skips normalize_arrow_array for a top-level VARIANT
    column whose Arrow type the SerDe reads directly, so dictionary metadata
    reaches it encoded. A VARIANT nested in ARRAY, MAP or STRUCT is still
    normalized with its parent. is_native_arrow_type, which the Arrow writer uses to choose
    its output shape, is unchanged.

Benchmark (be/benchmark/variant/benchmark_variant_arrow_input.hpp): one
4064-row batch of 24-field JSON objects (~1.2 KB of JSON text per row), read into a
VARIANT column, RELEASE build, before = master, after = this PR.

Input Shared metadata master this PR
JSON text (utf8) 1.7 KB rejected 12.3 ms
JSON text (utf8) 64 KB rejected 14.9 ms
struct<binary, binary> 1.7 KB 39.0 ms 6.3 ms (6.2x)
struct<binary, binary> 64 KB 531 ms 52.9 ms (10x)
dictionary metadata, as the stream reader reads it 1.7 KB 41.3 ms (decoded first) 6.0 ms (6.9x)
dictionary metadata, as the stream reader reads it 64 KB 620 ms (decoded first) 6.2 ms (100x)

Medians of 10 runs on one core of a c7i.8xlarge. On master, the
dictionary row is normalize_arrow_array followed by the SerDe, which is
what the stream reader did. In this PR the reader passes it through. The
plain struct with 64 KB metadata is still the slowest binary form, because
every row's copy of the metadata has to be compared to find that it is
shared; dictionary metadata avoids that.

End to end: Stream Load of the same 1M rows (24-field JSON objects, ~1.1 KB
each) into (id INT, v VARIANT), one FE and one BE, RELEASE build of this PR,
8 buckets, one load at a time, no compression, average of 3 runs (for the
struct<binary, binary> row, of the last 2: the first took 12.4 s, which looks
like a cold-cache outlier, though I did not confirm the cause). BE CPU is
the BE process's CPU time during the load. The stored values are identical
for every input form (same checksum of cast(v AS STRING)).

Input Distinct keys Bytes Load time BE CPU
JSON load (format=json, read_json_by_line) 120 1.08 GB 5.9 s 18.8 s
Arrow, JSON text 120 1.06 GB 6.7 s 19.1 s
Arrow, struct<binary, binary> 120 2.43 GB 5.5 s 18.2 s
Arrow, dictionary metadata 120 0.73 GB 5.2 s 17.3 s
JSON load (format=json, read_json_by_line) 4080 1.11 GB 7.2 s 26.8 s
Arrow, JSON text 4080 1.10 GB 8.5 s 28.3 s
Arrow, dictionary metadata 4080 0.76 GB 6.2 s 24.7 s

Most of the BE CPU is the write path, which is the same for every input form,
so skipping the JSON parse with binary input saves about 8% of BE CPU and
11-14% of load time here. Arrow JSON text costs slightly more than a JSON
load; it is for clients that already produce Arrow, not a speedup.

Release note

Stream Load with format=arrow can load VARIANT columns from JSON text
(utf8, large_utf8, binary, large_binary), and from Parquet Variant
binary struct<metadata, value> in either field order. Binary input with
large_binary children or a dictionary-encoded metadata child, which
already loaded, is now read without first being decoded to plain binary.

Check List (For Author)

  • Test:
    • Unit Test: DataTypeVariantV2SerdeArrowInputTest (13 new cases), with
      the existing DataTypeVariantV2Serde* and ArrowFlightVariantTest
      suites (59 tests, ASAN)
    • Regression test: load_p0/stream_load/test_arrow_stream_load_variant, run
      against a RELEASE FE/BE built from this branch (.out generated by the run)
    • Benchmark: before/after numbers above
  • Behavior changed: Yes. A VARIANT column in an Arrow Stream Load now
    accepts JSON text and the swapped field order instead of failing. JSON text
    is parsed like a JSON load: text that is not valid JSON and integer
    literals beyond 64 bits are stored as strings, and
    variant_max_json_key_length does not apply.
  • Does this need documentation: No

🤖 Generated with Claude Code

### What problem does this PR solve?

Issue Number: close apache#68890

Related PR: apache#68883

Problem Summary:

Stream Load with `format=arrow` could not load the Arrow forms clients
send for a VARIANT column. `DataTypeVariantV2SerDe::read_column_from_arrow`
accepted only the exact shape Doris writes for Arrow Flight,
`struct<metadata: binary, value: binary>` in that field order. It rejected
the other shapes:

- JSON text, one document per row (`utf8`, `large_utf8`, `binary`,
  `large_binary`), which is how most clients send semi-structured events;
- `large_binary` children, or the two fields in the other order (pyarrow
  builds the struct by name);
- a dictionary-encoded `metadata` child. A producer that encodes a record
  batch at a time has one metadata blob per batch. As a plain binary child,
  that blob is repeated in every row: about 1 KB per row for a batch mixing
  ~10 event sources and about 45 KB per row for one mixing all of them,
  against ~1.3 KB of value bytes. As `dictionary<int32, binary>` with one
  entry, it costs a few bytes per row.

On the reader side, FileScannerV2's Arrow stream reader normalizes every
column before the SerDe sees it, which decodes a dictionary into plain
binary. For dictionary metadata that copies the shared blob into every row,
and the SerDe then compares it row by row to find that all rows share it.

This PR:

1. Extends the VARIANT V2 Arrow reader to accept, with or without the
   `arrow.parquet.variant` extension:
   - JSON text in `utf8`/`large_utf8`/`binary`/`large_binary`, parsed with
     the same options as `parse_to_variant`. A NULL row is JSON null.
   - `struct<metadata, value>` in either field order with `binary` or
     `large_binary` children. Rows go through
     `ColumnVariantV2::EncodedRowsAppender`, which validates every row before
     appending and keeps a batch that shares one metadata blob in the
     single-metadata form. Before, each row was copied into a
     `VariantBatchBuilder` and then copied again into the column.
   - the same struct with `dictionary<integer, binary | large_binary>`
     metadata. It maps directly onto `ColumnVariantV2::insert_encoded_rows`:
     dictionary entries are the metadata blobs and indices are the metadata
     ids. When every row uses one entry, only that entry is passed, so no
     row's metadata is copied, hashed or compared.
   Every shape runs `ValidateFull()` on the slice and Variant metadata/payload
   validation before the destination changes, so a bad batch appends
   nothing. NULL struct rows become Variant null.
2. Adds `DataTypeVariantV2SerDe::is_arrow_input_type`. The FileScannerV2
   Arrow stream reader skips `normalize_arrow_array` for a VARIANT column
   whose Arrow type the SerDe reads directly, so dictionary metadata reaches
   it encoded. `is_native_arrow_type`, which the Arrow writer uses to choose
   its output shape, is unchanged.

Benchmark (`be/benchmark/variant/benchmark_variant_arrow_input.hpp`): one
4064-row batch of 24-field events (~1.3 KB of values per row), read into a
VARIANT column, RELEASE build, before = master, after = this PR.

| Input | Shared metadata | master | this PR |
|---|---|---|---|
| JSON text (`utf8`) | 1.7 KB | rejected | 12.3 ms |
| JSON text (`utf8`) | 64 KB | rejected | 14.9 ms |
| `struct<binary, binary>` | 1.7 KB | 39.0 ms | 6.3 ms (6.2x) |
| `struct<binary, binary>` | 64 KB | 531 ms | 52.9 ms (10x) |
| dictionary metadata, as the stream reader reads it | 1.7 KB | 41.3 ms (decoded first) | 6.0 ms (6.9x) |
| dictionary metadata, as the stream reader reads it | 64 KB | 620 ms (decoded first) | 6.2 ms (100x) |

Medians of 10 runs on one core of a c7i.8xlarge. On master, the
dictionary row is normalize_arrow_array followed by the SerDe, which is
what the stream reader did. In this PR the reader passes it through. The
plain struct with 64 KB metadata is still the slowest binary form, because
every row's copy of the metadata has to be compared to find that it is
shared; dictionary metadata avoids that.

### Release note

Stream Load with `format=arrow` can load VARIANT columns from JSON text
(`utf8`, `large_utf8`, `binary`, `large_binary`) or from Parquet Variant
binary `struct<metadata, value>` (with or without the `arrow.parquet.variant`
extension, `binary` or `large_binary` children, either field order, and the
`metadata` child optionally dictionary encoded).

### Check List (For Author)

- Test:
    - Unit Test: `DataTypeVariantV2SerdeArrowInputTest` (12 new cases), with
      the existing `DataTypeVariantV2Serde*` and `ArrowFlightVariantTest`
      suites (59 tests, ASAN)
    - Regression test: `load_p0/stream_load/test_arrow_stream_load_variant`, run
      against a RELEASE FE/BE built from this branch (`.out` generated by the run)
    - Benchmark: before/after numbers above
- Behavior changed: Yes. A VARIANT column in an Arrow Stream Load now
  accepts the Arrow types above instead of failing. Text that is not valid
  JSON fails the load, as other Arrow conversion errors do.
- Does this need documentation: No

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@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?

matanper and others added 3 commits October 28, 2026 13:53
…parse JSON text like JSON loads

### What problem does this PR solve?

Issue Number: close apache#68890

Related PR: apache#69767

Problem Summary:

Review follow-ups for the Arrow VARIANT reader added earlier in this PR:

1. A struct whose `metadata` child is dictionary encoded could carry an
   empty `value` cell, or an empty or NULL dictionary entry. `ValidateFull`
   accepts both, and the reader passed them to
   `ColumnVariantV2::insert_encoded_rows`, whose offset check is a
   `DORIS_CHECK` (abort on Debug/ASAN builds, internal error on Release).
   The reader now rejects them with INVALID_ARGUMENT naming the row or
   entry, as the plain binary struct path already did.
2. Arrow JSON text was parsed with `parse_to_variant`'s options, so one
   non-JSON string or a key over 255 bytes failed the whole load, while a
   JSON-format load of the same rows succeeds. It now uses the options of
   the Variant JSON deserializer, the same as a JSON load: text that is not
   JSON is kept as a string.
3. Tests: unit cases for empty values, empty/NULL dictionary entries (used
   and unused), and JSON-load parity; the regression suite now prints
   `v IS NULL`, loads a two-entry dictionary, and checks that a load with an
   empty value fails and loads nothing.
4. The stream reader comment notes that a VARIANT nested in ARRAY, MAP or
   STRUCT is still normalized with its parent.

### Release note

None

### Check List (For Author)

- Test:
    - Unit Test: `DataTypeVariantV2SerdeArrowInputTest` (13 cases) with the
      existing `DataTypeVariantV2Serde*` and `ArrowFlightVariantTest` suites
    - Regression test: `load_p0/stream_load/test_arrow_stream_load_variant`
- Behavior changed: Yes. Arrow JSON text that is not valid JSON is stored
  as a string, as in a JSON load, instead of failing the load.
- Does this need documentation: No

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
### What problem does this PR solve?

Issue Number: close apache#68890

Related PR: apache#69767

Problem Summary: The benchmark header and its row generator described the
data as events from event sources. The data is generic JSON objects with a
configurable number of distinct keys; describe it that way. No change to the
generated data or the measurements.

### Release note

None

### Check List (For Author)

- Test: No need to test (comment and helper rename only; clang-format checked)
- Behavior changed: No
- Does this need documentation: No

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@morningman

Copy link
Copy Markdown
Contributor

/review

@morningman

Copy link
Copy Markdown
Contributor

run buildall

@github-actions github-actions Bot 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.

Static review of PR 69767 at exact head 92b4c22 found no actionable defects and no existing P0/P1 thread to reconfirm. The change adds Arrow VARIANT JSON-text and Parquet-variant carriers, including large-binary and dictionary metadata, while preserving nested normalization. Goal and scope: the new SerDe dispatch, stream-reader binding, benchmark, unit tests, fixtures, and regression suite are focused on that behavior and the traced callers support the intended forms. Data correctness: requested row ranges are sliced logically; struct nulls become the canonical Variant null; metadata IDs and large offsets are checked; payload and metadata validation happen before ColumnVariantV2 mutation, and borrowed Arrow buffers are copied before the batch can be released. Error handling: invalid shapes, null children, dictionary bounds, empty bytes, malformed payloads, and oversized buffers return status through the exception boundary without partial destination appends. Memory/lifecycle: direct views live only through the synchronous append and the destination owns copied bytes; the scanner path is single-threaded for the batch and no new shared lock or lifecycle dependency was found. Compatibility: no Thrift/protobuf or storage-format change; top-level accepted carriers retain their wire type, while nested ARRAY/MAP/STRUCT paths continue recursive normalization. Parallel callers, nullable wrappers, extension unwrapping, benchmark registration, recursive BE test discovery, ordered regression queries, and failure-preservation coverage were checked. No new configuration or observability change applies. User focus was empty. Static-only limit: builds, unit tests, regression tests, and runtime parsing of the generated Arrow fixtures were not executed, as required by the review contract; nested end-to-end carrier coverage is a test gap without a demonstrated incorrect outcome. All assigned subagents returned NO_NEW_VALUABLE_FINDINGS in round 1, so the review converged.

Review converged after 1 round(s).

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.60% (36433/46947)
Line Coverage 62.88% (411980/655169)
Region Coverage 59.38% (349064/587845)
Branch Coverage 60.26% (161789/268481)

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69767

Problem Summary: The performance pipeline fails to compile the Variant Arrow
JSON reader with GCC 15.1.0 and -Werror. GCC reports the function-local static
constexpr json_null as unused even though the generic lambda references it.
Construct the string_view directly from the null string literal instead of
introducing that local constant. Arrow NULL rows still encode as JSON null,
and non-NULL rows keep their existing text.

### Release note

None

### Check List (For Author)

- Test:
    - Manual test: An isolated reproducer extracted from the original reader
      fails with the same unused-but-set-variable error on GCC 15.2.0. The
      fixed reader compiles with -std=gnu++20 -O3 -Wall -Wextra -Werror and
      passes NULL/non-NULL input checks for 32-bit and 64-bit array views.
    - Manual test: The fixed isolated reader also compiles and passes the
      same input checks with Apple Clang 21.0.0.
    - Formatting: Project clang-format and check-format scripts with version
      16, scoped to the modified file; git diff --check.
    - Full BE build, BE unit tests and regression tests were not run; this
      worktree has no configured BE build directory or compilation database.
- Behavior changed: No
- Does this need documentation: No
@morningman

Copy link
Copy Markdown
Contributor

run performance

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17589	5228	5067	5067
q2	2172	317	255	255
q3	10241	1445	829	829
q4	4686	463	334	334
q5	7440	827	524	524
q6	181	207	157	157
q7	752	793	599	599
q8	9255	1382	1070	1070
q9	5552	4221	4214	4214
q10	6823	1302	1025	1025
q11	444	245	231	231
q12	644	405	288	288
q13	18088	3657	3092	3092
q14	278	272	248	248
q15	q16	757	729	665	665
q17	1202	746	597	597
q18	6978	6175	6135	6135
q19	1114	980	613	613
q20	388	338	224	224
q21	5853	2466	2509	2466
q22	376	338	281	281
Total cold run time: 100813 ms
Total hot run time: 28914 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5991	5888	6153	5888
q2	737	628	575	575
q3	5667	5879	5221	5221
q4	2015	2166	1581	1581
q5	5810	5815	5593	5593
q6	241	187	144	144
q7	2251	2054	1860	1860
q8	2996	2679	2638	2638
q9	7967	7600	7450	7450
q10	3647	3576	3145	3145
q11	580	405	383	383
q12	689	664	518	518
q13	3297	3571	3040	3040
q14	283	296	265	265
q15	q16	664	692	622	622
q17	7784	6992	6911	6911
q18	12946	12155	12896	12155
q19	901	782	794	782
q20	2152	2144	1916	1916
q21	5583	4598	4945	4598
q22	514	440	402	402
Total cold run time: 72715 ms
Total hot run time: 65687 ms

@hello-stephen

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

query5	4315	597	448	448
query6	424	206	185	185
query7	4804	440	227	227
query8	333	175	151	151
query9	8786	3149	3186	3149
query10	497	313	275	275
query11	5992	3838	3558	3558
query12	146	92	87	87
query13	1248	457	320	320
query14	6152	3962	3653	3653
query14_1	3383	3378	3461	3378
query15	203	197	177	177
query16	938	414	408	408
query17	837	633	519	519
query18	2399	419	296	296
query19	197	157	130	130
query20	83	82	84	82
query21	217	127	106	106
query22	13021	13190	12832	12832
query23	13537	12671	12484	12484
query23_1	12541	12496	12613	12496
query24	7331	835	465	465
query24_1	463	479	474	474
query25	509	390	342	342
query26	1269	254	137	137
query27	2775	434	268	268
query28	4609	2031	1993	1993
query29	1570	611	452	452
query30	299	223	187	187
query31	1031	927	814	814
query32	153	93	99	93
query33	558	309	256	256
query34	878	841	506	506
query35	745	756	667	667
query36	826	839	733	733
query37	130	98	81	81
query38	1784	1742	1687	1687
query39	808	784	748	748
query39_1	749	742	739	739
query40	223	120	98	98
query41	70	67	68	67
query42	91	83	85	83
query43	347	361	315	315
query44	1340	698	702	698
query45	185	181	174	174
query46	838	968	585	585
query47	2946	2725	2912	2725
query48	299	309	226	226
query49	593	411	298	298
query50	680	276	206	206
query51	10599	10438	10332	10332
query52	87	80	71	71
query53	197	210	153	153
query54	261	203	189	189
query55	76	73	65	65
query56	233	242	240	240
query57	1661	1629	1597	1597
query58	301	272	283	272
query59	2179	2273	2016	2016
query60	287	256	241	241
query61	168	164	163	163
query62	403	346	296	296
query63	192	167	161	161
query64	2900	915	727	727
query65	3320	3273	3257	3257
query66	1789	414	320	320
query67	20158	20001	19915	19915
query68	3079	986	610	610
query69	372	288	247	247
query70	845	760	801	760
query71	303	231	202	202
query72	2736	2604	2339	2339
query73	515	524	291	291
query74	4643	4489	4348	4348
query75	2344	2293	1918	1918
query76	2320	1013	579	579
query77	324	366	271	271
query78	9727	9839	9178	9178
query79	979	904	535	535
query80	787	425	330	330
query81	564	322	270	270
query82	703	136	110	110
query83	272	195	178	178
query84	314	128	96	96
query85	967	412	356	356
query86	352	244	231	231
query87	2028	1904	1818	1818
query88	3765	2770	2747	2747
query89	330	280	253	253
query90	1706	159	167	159
query91	164	146	130	130
query92	99	101	88	88
query93	996	985	561	561
query94	499	319	268	268
query95	569	322	316	316
query96	698	469	236	236
query97	2427	2451	2303	2303
query98	167	152	150	150
query99	772	764	654	654
Total cold run time: 235108 ms
Total hot run time: 150958 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.26	0.09	0.09
query4	1.61	0.10	0.10
query5	0.26	0.24	0.24
query6	1.17	0.69	0.68
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.40	0.34	0.32
query10	0.60	0.57	0.60
query11	0.21	0.15	0.16
query12	0.18	0.15	0.15
query13	0.49	0.50	0.49
query14	1.04	1.02	1.00
query15	0.63	0.59	0.61
query16	0.35	0.31	0.31
query17	1.14	1.09	1.11
query18	0.20	0.18	0.19
query19	2.11	2.00	2.00
query20	0.02	0.01	0.02
query21	15.42	0.21	0.14
query22	4.77	0.06	0.06
query23	16.26	0.33	0.12
query24	2.89	0.52	0.31
query25	0.11	0.06	0.05
query26	0.99	0.22	0.16
query27	0.05	0.05	0.05
query28	3.20	0.79	0.36
query29	12.52	4.10	3.22
query30	0.29	0.13	0.10
query31	2.77	0.55	0.33
query32	3.22	0.59	0.50
query33	3.18	3.21	3.30
query34	15.30	3.99	3.41
query35	3.36	3.39	3.34
query36	0.56	0.46	0.43
query37	0.09	0.07	0.06
query38	0.06	0.04	0.03
query39	0.04	0.03	0.02
query40	0.18	0.14	0.13
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.05	0.03	0.03
Total cold run time: 96.29 s
Total hot run time: 24.19 s

@morningman

Copy link
Copy Markdown
Contributor

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17599	5134	5009	5009
q2	2157	303	245	245
q3	10257	1346	827	827
q4	4677	451	333	333
q5	7425	799	532	532
q6	182	186	151	151
q7	741	792	595	595
q8	9253	1292	1076	1076
q9	5474	4196	4174	4174
q10	6825	1304	1015	1015
q11	450	252	234	234
q12	638	398	274	274
q13	18092	3591	3010	3010
q14	266	262	245	245
q15	q16	724	724	654	654
q17	1186	743	577	577
q18	6928	6158	6111	6111
q19	1108	963	585	585
q20	377	328	226	226
q21	4949	2559	2490	2490
q22	368	322	272	272
Total cold run time: 99676 ms
Total hot run time: 28635 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5893	5985	6251	5985
q2	747	610	573	573
q3	5540	5697	5268	5268
q4	2246	2146	1552	1552
q5	5731	5807	5763	5763
q6	240	192	140	140
q7	2265	1962	1804	1804
q8	2863	2440	2462	2440
q9	7519	7490	7431	7431
q10	3624	3536	3130	3130
q11	576	398	377	377
q12	685	661	506	506
q13	3243	3631	3076	3076
q14	289	291	260	260
q15	q16	680	686	612	612
q17	7822	7025	6852	6852
q18	13027	12196	12856	12196
q19	896	812	787	787
q20	2149	2134	1920	1920
q21	5528	4549	4661	4549
q22	513	462	401	401
Total cold run time: 72076 ms
Total hot run time: 65622 ms

@hello-stephen

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

query5	4318	602	437	437
query6	443	199	187	187
query7	4832	457	221	221
query8	321	167	149	149
query9	8783	3134	3156	3134
query10	470	311	258	258
query11	6068	3872	3563	3563
query12	142	91	87	87
query13	1239	418	316	316
query14	6154	3913	3725	3725
query14_1	3432	3367	3413	3367
query15	209	213	182	182
query16	957	437	414	414
query17	848	659	536	536
query18	2418	416	314	314
query19	211	178	143	143
query20	88	93	83	83
query21	208	137	107	107
query22	12872	12991	12788	12788
query23	13623	12856	12452	12452
query23_1	12540	12460	12559	12460
query24	7379	824	474	474
query24_1	511	501	516	501
query25	613	431	365	365
query26	1314	256	146	146
query27	2757	445	277	277
query28	4716	2006	2002	2002
query29	1576	602	443	443
query30	305	223	184	184
query31	1004	930	825	825
query32	151	93	95	93
query33	529	302	239	239
query34	889	852	509	509
query35	745	759	641	641
query36	810	808	745	745
query37	132	101	82	82
query38	1763	1770	1652	1652
query39	799	801	756	756
query39_1	732	728	746	728
query40	220	118	102	102
query41	71	67	68	67
query42	88	85	84	84
query43	346	366	335	335
query44	1315	685	698	685
query45	182	181	166	166
query46	851	972	564	564
query47	2961	2870	2860	2860
query48	319	301	215	215
query49	580	408	294	294
query50	687	268	211	211
query51	10488	10704	10357	10357
query52	79	78	70	70
query53	185	204	147	147
query54	242	190	174	174
query55	67	66	61	61
query56	238	204	196	196
query57	1653	1627	1582	1582
query58	282	256	259	256
query59	2133	2224	1981	1981
query60	297	244	226	226
query61	146	146	146	146
query62	387	335	281	281
query63	193	157	162	157
query64	2707	930	759	759
query65	3322	3260	3279	3260
query66	1783	413	293	293
query67	20106	20235	20087	20087
query68	3010	989	609	609
query69	377	289	247	247
query70	831	775	762	762
query71	290	227	209	209
query72	2738	2632	2300	2300
query73	510	516	295	295
query74	4614	4476	4355	4355
query75	2339	2271	1911	1911
query76	2310	1013	583	583
query77	345	369	263	263
query78	9793	9768	9185	9185
query79	999	832	525	525
query80	895	417	348	348
query81	576	321	274	274
query82	577	133	114	114
query83	303	190	181	181
query84	312	118	111	111
query85	874	422	361	361
query86	357	241	235	235
query87	2020	1939	1812	1812
query88	3738	2742	2715	2715
query89	329	275	242	242
query90	1784	154	166	154
query91	159	150	128	128
query92	99	99	100	99
query93	993	976	559	559
query94	523	299	252	252
query95	575	388	296	296
query96	684	478	234	234
query97	2429	2417	2316	2316
query98	159	153	160	153
query99	767	763	670	670
Total cold run time: 234971 ms
Total hot run time: 151039 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.26	0.08	0.09
query4	1.61	0.10	0.11
query5	0.23	0.25	0.24
query6	1.18	0.67	0.67
query7	0.04	0.00	0.00
query8	0.05	0.04	0.04
query9	0.41	0.36	0.35
query10	0.56	0.57	0.61
query11	0.21	0.14	0.14
query12	0.19	0.15	0.14
query13	0.49	0.48	0.48
query14	1.03	1.03	0.99
query15	0.62	0.62	0.62
query16	0.36	0.34	0.35
query17	1.10	1.14	1.15
query18	0.20	0.18	0.18
query19	2.07	1.98	2.08
query20	0.02	0.01	0.02
query21	15.49	0.20	0.14
query22	4.96	0.06	0.04
query23	16.27	0.32	0.12
query24	2.79	0.63	0.31
query25	0.11	0.06	0.07
query26	1.17	0.21	0.16
query27	0.05	0.04	0.04
query28	3.67	0.76	0.36
query29	12.50	4.09	3.28
query30	0.28	0.14	0.10
query31	2.77	0.56	0.33
query32	3.22	0.59	0.50
query33	3.27	3.25	3.16
query34	15.35	3.99	3.37
query35	3.34	3.33	3.34
query36	0.56	0.43	0.42
query37	0.09	0.06	0.06
query38	0.04	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.14	0.14
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.03
Total cold run time: 97.06 s
Total hot run time: 24.2 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.63% (36704/47278)
Line Coverage 63.02% (415939/659978)
Region Coverage 59.32% (351223/592059)
Branch Coverage 60.30% (163176/270594)

matanper and others added 2 commits November 2, 2026 11:01
…68890

Resolve the benchmark_main.cpp include conflict: master moved the full benchmark list under #ifndef DORIS_BENCHMARK_HEADER; keep benchmark_variant_arrow_input.hpp in that list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…68890

Resolve the arrow_stream_reader.cpp include conflict: keep both core/data_type_serde/arrow_parent_nulls.h (master) and data_type_variant_v2_serde.h (this PR). The VARIANT normalization skip and master's per-batch mask_arrow_descendants_not_visible() pass compose: the mask treats extension and dictionary arrays as leaves, and the Variant reader reads no child of a NULL struct row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@matanper
matanper requested a review from Mryange as a code owner November 10, 2026 08:06
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.

[Feature] Stream Load format=arrow into VARIANT columns

3 participants