-
-
Notifications
You must be signed in to change notification settings - Fork 0
Understanding Parquet Metadata
iparq is a tool for inspecting the metadata inside Apache Parquet files. This page explains the Parquet concepts that iparq exposes so you can better understand what the output means and why it matters.
Apache Parquet is a columnar storage format designed for analytics and big data workloads. Instead of storing data row by row, it stores values for each column together, which makes it efficient for:
- Reading only the columns a query needs
- Compressing similar values very effectively
- Supporting rich encodings and metadata for query optimization
Parquet is widely used across the modern data ecosystem, including tools such as Apache Spark, DuckDB, Pandas, Apache Arrow, Trino, and many cloud data platforms.
At a high level, a Parquet file is organized like this:
- File metadata
- Row groups
- Column chunks
- Pages
The file metadata lives in the Parquet footer and describes the file as a whole: schema, creator, row counts, row group counts, version information, and other details. This is the information represented by ParquetMetaModel in iparq.
A row group is a horizontal partition of the dataset. Each row group contains a subset of rows for every column in the schema.
Row groups matter because they are often the unit of parallel reading and skipping. If a query engine can rule out a row group using statistics or bloom filters, it avoids reading that part of the file.
Within each row group, each column is stored in its own column chunk. So for every row group and every column, there is one corresponding column chunk.
This is where you see details such as:
- compression codec
- statistics
- encryption metadata
- sizes
Pages are the smallest unit of storage inside a column chunk. Data pages hold encoded values, and other page types can hold indexes or dictionaries.
Most end users do not inspect pages directly, but pages are where Parquet’s encoding and compression efficiency is actually realized.
iparq shows top-level file metadata such as:
-
created_by: Which engine or library created the file, for exampleparquet-cpp-arrow version 14.0.2,parquet-mr, or similar -
num_columns: Number of columns in the schema -
num_rows: Total row count in the file -
num_row_groups: Number of row groups in the file; this can affect parallelism and skipping behavior -
format_version: Parquet format version, such as1.0,2.4, or2.6 -
serialized_size: Size of the metadata footer in bytes
These fields are often the fastest way to understand how a file was produced and how it is laid out.
Parquet stores data column by column, which makes compression especially effective. iparq shows the compression codec used for each column chunk.
Common codecs include:
- SNAPPY: fast, widely supported, moderate compression ratio
- ZSTD: excellent balance of compression ratio and speed
- GZIP: high compression ratio, but slower
- LZ4: very fast, often with lower compression than ZSTD or GZIP
- BROTLI: strong compression, often used when size matters more than speed
- UNCOMPRESSED: no compression at all
Different engines choose different defaults, and those choices can have a real impact on storage cost and query performance. In many ways, this question of “what compression is this Parquet file actually using?” is what motivated the creation of iparq.
A bloom filter is a probabilistic data structure used for fast membership testing.
In Parquet, bloom filters can help a query engine decide that a row group definitely does not contain a value, which allows it to skip reading that data entirely.
Important properties:
- False positives are possible
- False negatives are not
That means a bloom filter may sometimes say “maybe present” when the value is not there, but it should not say “definitely absent” when the value is actually present.
This can dramatically speed up selective lookups, especially for equality filters on large datasets.
Further reading: https://duckdb.org/2025/03/07/parquet-bloom-filters-in-duckdb.html
Parquet supports column-level encryption. iparq detects encrypted columns by checking whether is_crypto_metadata_set() is true for a column chunk.
Encrypted columns are shown with a 🔒 indicator.
This is useful when auditing files, verifying security-sensitive pipelines, or understanding why certain metadata may be limited.
Parquet can store column statistics in metadata, including minimum and maximum values for a column chunk.
These statistics enable predicate pushdown. For example, if a row group’s max value for a date column is 2024-01-31, then a filter for dates in March can skip that row group without reading it.
iparq shows min/max values per column per row group so you can see what the query engine may use for skipping.
Newer PyArrow versions expose:
is_min_value_exactis_max_value_exact
These fields indicate whether the stored min/max values are exact or whether they may be truncated or approximate.
This matters because query optimizers need to know whether statistics are safe to rely on for pruning decisions. Exactness helps explain both correctness and optimization behavior.
With the --sizes flag, iparq shows additional storage information such as:
num_values-
total_compressed_sizein human-readable form - compression ratio, computed as uncompressed size divided by compressed size
This helps you understand how efficiently each column is stored and which columns are driving space usage.
These details are not just metadata trivia:
- Different engines produce different Parquet files
- Knowing compression helps optimize storage and performance
- Bloom filters can dramatically speed up point lookups
- Statistics enable predicate pushdown optimization
- Understanding these details helps debug performance issues
If two tools produce very different file sizes or query speeds from the same data, Parquet metadata is often where the explanation starts.
- Apache Parquet specification: https://parquet.apache.org/
- DuckDB Parquet encodings blog: https://duckdb.org/2025/01/22/parquet-encodings.html
- DuckDB Bloom filters blog: https://duckdb.org/2025/03/07/parquet-bloom-filters-in-duckdb.html