[
https://issues.apache.org/jira/browse/HIVE-29866?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18111081#comment-18111081
]
László Bodor commented on HIVE-29866:
-------------------------------------
the fix makes the query pass and make the data IO cached properly, first run:
{code}
INFO : LLAP IO Summary
INFO :
----------------------------------------------------------------------------------------------
INFO : VERTICES ROWGROUPS META_HIT META_MISS DATA_HIT DATA_MISS TOTAL_IO
INFO :
----------------------------------------------------------------------------------------------
INFO : Map 1 0 0 0 0B 1.61GB 4165.64s
INFO :
----------------------------------------------------------------------------------------------
INFO :
INFO : FileSystem Counters Summary
INFO :
INFO : Scheme: S3A
INFO :
----------------------------------------------------------------------------------------------
INFO : VERTICES BYTES_READ READ_OPS LARGE_READ_OPS
BYTES_WRITTEN WRITE_OPS
INFO :
----------------------------------------------------------------------------------------------
INFO : Map 1 9.30GB 277 0
0B 0
INFO : Reducer 2 0B 0 0
0B 0
INFO :
----------------------------------------------------------------------------------------------
+---------+
| _c0 |
+---------+
| 275000 |
+---------+
1 row selected (201.147 seconds)
{code}
second run:
{code}
INFO : LLAP IO Summary
INFO :
----------------------------------------------------------------------------------------------
INFO : VERTICES ROWGROUPS META_HIT META_MISS DATA_HIT DATA_MISS TOTAL_IO
INFO :
----------------------------------------------------------------------------------------------
INFO : Map 1 0 0 0 9.29GB 0B 0.10s
INFO :
----------------------------------------------------------------------------------------------
INFO :
INFO : FileSystem Counters Summary
INFO :
INFO : Scheme: S3A
INFO :
----------------------------------------------------------------------------------------------
INFO : VERTICES BYTES_READ READ_OPS LARGE_READ_OPS
BYTES_WRITTEN WRITE_OPS
INFO :
----------------------------------------------------------------------------------------------
INFO : Map 1 0B 278 0
0B 0
INFO : Reducer 2 0B 0 0
0B 0
INFO :
----------------------------------------------------------------------------------------------
+---------+
| _c0 |
+---------+
| 275000 |
+---------+
1 row selected (5.474 seconds)
{code}
> Optimize LLAP IO cache encoding path for text tables with MultiDelimitSerDe
> ---------------------------------------------------------------------------
>
> Key: HIVE-29866
> URL: https://issues.apache.org/jira/browse/HIVE-29866
> Project: Hive
> Issue Type: Improvement
> Reporter: László Bodor
> Assignee: László Bodor
> Priority: Major
> Labels: pull-request-available
> Attachments: Screenshot 2026-09-03 at 13.56.34.png,
> heap-dump_Top_Components.zip
>
>
> *MultiDelimitSerDe currently OOMs in LLAP text-cache encoding*
> {*}TLDR{*}: LLAP OOMs while encoding large rows from {*}MultiDelimitSerDe{*},
> please find Eclipse MAT HTML report for the same:
> [^heap-dump_Top_Components.zip]
> {*}Details{*}:
> When LLAP ingests text and writes it into its ORC-encoded cache, the routing
> gate in
> [{{VectorDeserializeOrcWriter.create()}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/llap-server/src/java/org/apache/hadoop/hive/llap/io/encoded/VectorDeserializeOrcWriter.java#L101]
> today is:
> {code:java}
> if (... || !(serDe instanceof LazySimpleSerDe)) {
> return new DeserializerOrcWriter(serDe, sourceOi, allocSize);
> }
> {code}
> ({{{}DeserializerOrcWriter{}}} lives as an inner class in
> [{{SerDeEncodedDataReader}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/llap-server/src/java/org/apache/hadoop/hive/llap/io/encoded/SerDeEncodedDataReader.java#L1564].)
> {{MultiDelimitSerDe}} fails the check, so every row travels through
> {{{}DeserializerOrcWriter{}}}, the generic per-row fallback. For each row it:
> # Calls {{serDe.deserialize(Writable)}} → a fresh
> *[{{LazyStruct}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyStruct.java]*
> wrapping…
> # …a fresh
> *[{{LazyString}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyString.java]
> /
> [{{LazyInteger}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyInteger.java]
> / …* object per column (writable + underlying byte buffer refs).
> # Walks the struct through an {{ObjectInspector}} — every field getter
> allocates a *{{{}Text{}}}/{{{}IntWritable{}}}/…* to hand to the ORC writer.
> # ORC's {{TreeWriter}} then re-encodes those objects into columnar buffers.
> For a wide row (thousands of columns), that's {*}~1 struct + ~N lazy field
> objects + ~N writables per row{*}, all short-lived. Combined with LLAP's
> normal cache-fill pressure, the daemon runs out of heap.
> The vectorized path avoids all of this:
> [{{LazySimpleDeserializeRead.topLevelParse()}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/serde/src/java/org/apache/hadoop/hive/serde2/lazy/fast/LazySimpleDeserializeRead.java#L419]
> scans the raw bytes into a reused
> [{{VectorizedRowBatch}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/storage-api/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizedRowBatch.java#L40]
>
> ([{{DEFAULT_SIZE=1024}}|https://github.com/apache/hive/blob/bff3870c637184d096c1d6789761e0c0afdd6037/storage-api/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizedRowBatch.java#L66]
> rows at a time, fixed-size column vectors, {*}zero per-row allocation{*}).
> Wiring MultiDelimit into that path is what the fix does.
> please also find (sorry about dark mode here, the winner is StructTreeWriter):
> !Screenshot 2026-09-03 at 13.56.34.png|width=783,height=130!
> 12 instances most probably belong to 12 IO threads in the LLAP daemon where
> this investigation took place
>
> Repro steps, kinda pseudo:
> h2. How to reproduce
> # Create a MultiDelimit text table:
> {code:sql}
> CREATE TABLE mdelim_test (a STRING, b STRING, c STRING)
> ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.MultiDelimitSerDe'
> WITH SERDEPROPERTIES ('field.delim'='~|')
> STORED AS TEXTFILE;
> {code}
> # Load a large text file with {{~|}} as the field separator (wide rows and/or
> many rows amplify the effect).
> # On LLAP with cache enabled ({{hive.llap.io.enabled=true}}), run:
> {code:sql}
> SELECT COUNT(*) FROM mdelim_test;
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)