<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged apache-parquet</title>
<link>https://coderlegion.com/tag/apache-parquet</link>
<description>Powered by Question2Answer</description>
<item>
<title>Understanding Parquet File Format</title>
<link>https://coderlegion.com/30266/understanding-parquet-file-format</link>
<description>&lt;h3 id=&quot;what-is-a-file-format-&quot;&gt;What is a File Format?&lt;/h3&gt;
&lt;p&gt;A file format defines how data is structured and stored so that software can read and write it consistently.&lt;/p&gt;
&lt;p&gt;Think of it as the container for your data. Just like music comes in MP3, WAV, or FLAC, data files also come in different formats depending on the use case.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Common data file formats:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CSV – Simple text-based, rows separated by commas (easy to use, but&lt;br&gt;
large in size and no compression).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON – Flexible, hierarchical (good for APIs but verbose).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avro – Row-based binary format, compact, supports schema evolution &lt;br&gt;
(common in streaming).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ORC – Columnar format optimized for Hadoop and Hive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parquet – Columnar format designed for analytics and compression &lt;br&gt;
efficiency.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;introduction-to-parquet&quot;&gt;Introduction to Parquet&lt;/h3&gt;
&lt;p&gt;If you work with data, you have probably heard the term Parquet come up in conversations about data lakes, analytics, or cloud storage. But what exactly is it, and why does everyone seem to love it?&lt;/p&gt;
&lt;h3 id=&quot;the-everyday-analogy-organizing-your-groceries&quot;&gt;The Everyday Analogy: Organizing Your Groceries&lt;/h3&gt;
&lt;p&gt;Imagine you run a grocery delivery service, and you have to store all the items customers ordered.&lt;/p&gt;
&lt;p&gt;You could store them in two ways:&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;&lt;em&gt;Row-based storage (like CSV):&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;You put one of each item from an order into a bag: milk, bread, apples, and pasta all together. To find all the bread you have sold, you have to open every bag and dig around to see whether it is inside.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Column-based storage (like Parquet):&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Instead of mixing, you group similar items together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One box for all the milk&lt;/li&gt;
&lt;li&gt;One box for all the bread&lt;/li&gt;
&lt;li&gt;One box for all the apples&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you need all the bread you have sold, you simply open the bread box, no need to touch anything else.&lt;/p&gt;
&lt;p&gt;That is Parquet in action, organized storage that makes retrieval faster and more efficient.&lt;/p&gt;
&lt;h3 id=&quot;the-technical-view&quot;&gt;The Technical View&lt;/h3&gt;
&lt;p&gt;Parquet is an open-source, columnar storage format developed by Twitter and Cloudera, now an Apache project. It is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Self-describing – Metadata in the file footer stores schema, number&lt;br&gt;
of rows, and statistics.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Highly compressed – Supports Snappy, Gzip, ZSTD, and more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Structured internally into:&lt;br&gt;
&lt;strong&gt;Row Groups&lt;/strong&gt; → subsets of rows (horizontal partitions).&lt;br&gt;
&lt;strong&gt;Column Chunks&lt;/strong&gt; → data for each column inside a row group (vertical partitions).&lt;br&gt;
&lt;strong&gt;Pages&lt;/strong&gt; → the smallest unit of storage, making reads efficient.&lt;br&gt;
&lt;strong&gt;Magic Number (PAR1)&lt;/strong&gt; – Ensures the file is recognized as Parquet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This hybrid layout balances efficient columnar reads with manageable write performance.&lt;/p&gt;
&lt;h3 id=&quot;why-choose-parquet-over-other-formats-&quot;&gt;Why Choose Parquet Over Other Formats?&lt;/h3&gt;
&lt;p&gt;Now that we understand Parquet, let us see why it stands out compared to other formats.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSV – Human-readable but inefficient; no compression or schema&lt;br&gt;
support.&lt;/li&gt;
&lt;li&gt;JSON – Flexible for nested data, but verbose and large in size.&lt;/li&gt;
&lt;li&gt;Avro – Great for row-based streaming but not optimized for analytics.&lt;/li&gt;
&lt;li&gt;ORC – Similar to Parquet, optimized for Hadoop and Hive workloads.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Parquet vs the rest:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Much smaller file sizes due to efficient compression&lt;/li&gt;
&lt;li&gt;Faster query performance with column pruning and predicate pushdown&lt;/li&gt;
&lt;li&gt;Widely supported across Spark, Hive, Presto, Trino, BigQuery,&lt;br&gt;
Snowflake, AWS Athena, and more&lt;/li&gt;
&lt;li&gt;Ideal for data lakes and analytical workloads&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-data-is-written-in-parquet&quot;&gt;How Data is Written in Parquet&lt;/h3&gt;
&lt;p&gt;When writing data into a Parquet file, the process follows a layered structure:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=6044621059311078360&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Rows are collected into Row Groups&lt;/strong&gt;            &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instead of writing each record one by one (like CSV), Parquet groups&lt;br&gt;
multiple rows together into a Row Group (horizontal partition).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Within each Row Group, data is split into Column Chunks&lt;/strong&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each column’s values are stored together → Column A values go into &lt;br&gt;
Column Chunk A, Column B values into Column Chunk B, and so on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This preserves the columnar storage advantage.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Column Chunks are broken into Pages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Pages are the smallest unit of storage in Parquet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data Pages → contain the actual column data&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dictionary Pages → optionally store dictionaries used for dictionary encoding&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional Page Indexes can provide additional information for&lt;br&gt;
efficiently locating and skipping pages:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Column Index → stores statistics such as min/max values for pages&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offset Index → stores the locations and sizes of pages&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Metadata is written into the File Footer&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Contains schema, row count, statistics (min/max per column), and row&lt;br&gt;
group metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Makes Parquet a self-describing format.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Magic Number (PAR1) is added&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At the start and end of the file → ensures the file can be validated&lt;br&gt;
as a Parquet file.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-data-is-read-from-a-parquet-file&quot;&gt;How Data is Read from a Parquet File&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=17966435297597599916&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File Footer Read First&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Parquet does not scan the entire file right away. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It jumps directly to the footer, where all the metadata is stored.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Metadata tells the engine:&lt;br&gt;
Schema (what columns exist)&lt;br&gt;
Number of rows&lt;br&gt;
Statistics for each column in each row group (min/max)&lt;br&gt;
Row group and column chunk offsets (where the data lives in the file)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;➡️ &lt;em&gt;This helps the engine decide which parts of the file to actually read.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Predicate Pushdown &amp;amp; Column Pruning&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the query only needs certain columns (SELECT name, age), only&lt;br&gt;
those column chunks are accessed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the query has filters (WHERE age &amp;gt; 30), Parquet uses min/max stats&lt;br&gt;
in metadata to skip entire row groups that don’t match.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;➡️ &lt;em&gt;This reduces I/O drastically compared to row-based formats.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reading Row Groups&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The engine opens only the relevant row groups.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside each row group, it locates the column chunks needed for the&lt;br&gt;
query.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Decompression &amp;amp; Decoding Pages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Column chunks are split into pages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each page is decompressed (Snappy, Gzip, ZSTD, etc.) and decoded&lt;br&gt;
(Dictionary, RLE, Delta encoding).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pages are read into memory one at a time, which is efficient.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Reconstructing Results&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Once the engine reads, decompresses, and decodes the relevant column&lt;br&gt;
data, it reconstructs the requested rows and columns.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The engine materializes the final output as a result set for the&lt;br&gt;
query.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;parquet-file-size-small-vs-large&quot;&gt;Parquet File Size: Small vs Large&lt;/h3&gt;
&lt;p&gt;The size of each Parquet file matters a lot for performance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Too Small Files (&amp;lt; 50 MB each)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Too much metadata and file-open operations.&lt;/li&gt;
&lt;li&gt;Increases overhead for query engines (Spark, Presto, Hive).&lt;/li&gt;
&lt;li&gt;Known as the small files problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Too Large Files (&amp;gt; 1 GB each)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slows down reads and reduces parallelism.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;💡 &lt;strong&gt;Ideal File Size:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;256 MB to 1 GB for most big data frameworks.&lt;/li&gt;
&lt;li&gt;Large enough to compress well, small enough for parallelism.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-data-types-affect-compression-and-file-size-&quot;&gt;How Data Types Affect Compression (and File Size)&lt;/h3&gt;
&lt;p&gt;Parquet’s efficiency is heavily influenced by data type selection:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strings vs Integers:&lt;/strong&gt; Integers compress far better than storing&lt;br&gt;
numbers as strings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decimals vs Floats:&lt;/strong&gt; Decimals (fixed precision) often compress better.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Categorical Data:&lt;/strong&gt; Repeated values (like “USA”) compress extremely&lt;br&gt;
well with dictionary encoding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timestamps&lt;/strong&gt;: Storing as INT64 (epoch values) is more efficient than strings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Tip: Choose the most precise and smallest data type possible to save space and improve query speed.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;encoding-strategies-used-in-parquet&quot;&gt;Encoding Strategies used in Parquet&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3891040807583055239&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Run Length Encoding (RLE)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Stores consecutive repeated values as a single value + a count.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Columns with long runs of the same value (e.g., flags, booleans, country/state codes).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Extremely efficient for repetitive data, reduces size drastically.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Example:

Raw → A A A A B B C C C
RLE → (A,4), (B,2), (C,3)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Dictionary Encoding&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Builds a dictionary of unique values in a column and replaces each value with a small index reference.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Low-cardinality columns (few unique values, but repeated often).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Saves space when values repeat often, lookups are fast.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Example:

Raw → USA, USA, CAN, USA, CAN, MEX
Dictionary → {0: USA, 1: CAN, 2: MEX}
Encoded → 0, 0, 1, 0, 1, 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Delta Encoding&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Stores the difference (delta) between consecutive values instead of storing full values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Sequential/numeric data like timestamps, IDs, counters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Great for compressing increasing sequences, works well with integers and dates.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Example:

Raw → 100, 105, 110, 115
Delta → 100, +5, +5, +5
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;parquet-optimization-amp-best-practices&quot;&gt;Parquet Optimization &amp;amp; Best Practices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Predicate Pushdown&lt;/strong&gt; – Enable in your query engine to filter row groups&lt;br&gt;
at scan time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compression Codecs&lt;/strong&gt; &lt;br&gt;
Snappy: Fast, decent ratio&lt;br&gt;
Gzip: Higher compression, slower&lt;br&gt;
ZSTD: Good balance&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid Small Files&lt;/strong&gt; – Merge into larger files to reduce metadata&lt;br&gt;
overhead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Row Group Size&lt;/strong&gt; – Balance between compression (bigger row groups) and&lt;br&gt;
parallelism (smaller ones).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encoding Strategies &lt;/strong&gt;&lt;br&gt;
Dictionary Encoding for low-cardinality strings&lt;br&gt;
Run-Length Encoding for repeated values&lt;br&gt;
Delta Encoding for incremental numbers like timestamps&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sort Data&lt;/strong&gt; – Sorting on commonly filtered columns improves compression&lt;br&gt;
and predicate pushdown.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ACID Transactions&lt;/strong&gt; – Parquet itself does not provide ACID, use table formats like Delta Lake, Iceberg, or Hudi for transactional&lt;br&gt;
guarantees.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Parquet has become a default choice in the modern data stack because it offers the best of both worlds like compact storage and fast analytics.&lt;/p&gt;
&lt;p&gt;By understanding how it works internally (row groups, column chunks, pages) and following best practices (ideal file sizes, data types, compression, and encodings), you can save costs, improve query speeds, and build scalable pipelines.&lt;/p&gt;
&lt;h3 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h3&gt;
&lt;p&gt;For a deeper dive into Parquet’s internals, file layout, and optimizations, check out “&lt;a rel=&quot;nofollow&quot; href=&quot;https://vutr.substack.com/p/the-overview-of-parquet-file-format&quot;&gt;The Overview of Parquet File Format&lt;/a&gt;” by Vu Trinh. It’s a clear and insightful read for data engineers looking to go beyond the basics.&lt;/p&gt;
&lt;p&gt;In short, Parquet is the “&lt;strong&gt;organized pantry&lt;/strong&gt;” of the data world: efficient, structured, and always ready when you need it.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30266/understanding-parquet-file-format</guid>
<pubDate>Thu, 08 Oct 2026 11:42:51 +0000</pubDate>
</item>
</channel>
</rss>