Deserialization

ComputeAlex Merced

Core Definition

Deserialization is the exact inverse of serialization. It is the process of taking a stream of raw, flat bytes (retrieved from a storage medium like a hard drive or received over a network connection) and reconstructing it into a complex, in-memory data structure or object that a programming language or application can understand and manipulate.

In the open data lakehouse, deserialization is often the most significant bottleneck in query performance. When a query engine like Trino or Apache Spark reads a Parquet file from Amazon S3, the data arrives as an optimized, compressed binary stream. The engine must allocate memory, parse the bytes according to the file’s schema, and instantiate the corresponding objects (like Java strings, integers, or complex arrays) in RAM before any mathematical filtering or aggregation can occur.

Diagram 1: Conceptual Architecture

Deserialization Concept

Implementation and Operations

The cost of deserialization in big data is staggering. In many traditional Hadoop/Spark workloads, CPU profiling reveals that over 50% of the total CPU time is spent simply deserializing data.

To combat this, modern data architectures have introduced several radical innovations. One such innovation is Apache Arrow. Arrow defines a standardized, language-agnostic, in-memory columnar format. By ensuring that systems (like Python Pandas and a C++ query engine) use the exact same in-memory structure, Arrow enables “Zero-Copy Reads.” Data can be shared between systems without ever undergoing the costly serialization/deserialization cycle.

Furthermore, modern vectorized query engines (like DuckDB and StarRocks) are designed to minimize deserialization overhead by operating directly on compressed data or by keeping the data in raw columnar vectors for as long as possible during execution, only fully deserializing the final, much smaller result set.

Diagram 2: Operational Flow

Deserialization Flow

Summary and Tradeoffs

Deserialization is an unavoidable necessity when moving data from disk to memory. The primary tradeoff in data engineering is choosing storage formats that balance compression ratios with deserialization speed. Formats like Parquet are heavily optimized to allow query engines to deserialize only the specific columns needed for a query (Projection Pushdown), avoiding the catastrophic cost of deserializing an entire massive dataset just to access a single field.

Usually the More Expensive Direction

Deserialization is typically slower than serialization in analytical workloads, and it happens more often. Data is written once and read many times, so the read path’s decoding cost is paid repeatedly for every byte written.

Reconstructing values is more work than emitting them. The reader must interpret encodings, resolve dictionary references, apply definition and repetition levels to reconstruct nulls and nested structure, and materialize values into whatever the engine’s execution layer expects.

The Parquet Read Path

Reading a Parquet column involves several distinct steps, each with its own cost:

  1. Fetch the byte range for the relevant column chunk from object storage.
  2. Decompress the pages using the codec the file was written with.
  3. Decode the encoding layer, expanding run-length and bit-packed representations.
  4. Resolve the dictionary, replacing indices with values where dictionary encoding was used.
  5. Reconstruct nulls and nesting from definition and repetition levels.
  6. Materialize into the engine’s in-memory representation.

Steps 2 through 5 are what people mean by deserialization, and step 6 is where an engine either does well or badly.

Vectorized Readers

The largest single improvement available is decoding in batches rather than row at a time. A row-at-a-time reader performs a method call per value with branching on type and nullability, which defeats CPU pipelining and prevents vector instructions from being used.

A vectorized reader decodes a column into a batch of values at once, typically a few thousand, with the type known for the whole batch. This turns per-value branching into a tight loop the processor can execute efficiently, and improvements of several times are common rather than exceptional.

This is why engines advertise vectorized Parquet readers, and why a query that seems slow relative to its data volume is worth checking against reader configuration before other tuning.

Avoiding the Work Entirely

The fastest deserialization is the kind that does not happen. Every layer of skipping in a lakehouse exists to reduce how many bytes reach the decoder: partition pruning removes files, min/max statistics remove row groups, dictionary pages remove column chunks, and projection removes columns.

Tuning the decode path helps at the margin. Reading less data helps by orders of magnitude, which is why sort order and partitioning have more effect on query time than reader settings.

Visual Architecture

Deserialization Concept

Deserialization Flow