Parquet

On this page 7

Parquet, formally Apache Parquet, is an open-source columnar file format for storing large analytical datasets, in which the values of each column are stored together, compressed and accompanied by statistics. Among data formats, it is the de facto standard for data lakes and analytical pipelines, supported by Spark, Trino, DuckDB, pandas, Polars and most cloud warehouses.

Unlike row-oriented text formats such as CSV or JSON, a Parquet file is binary, typed and self-describing: it carries its own schema and metadata. Query engines can read only the columns and row ranges they need, which typically makes analytical scans far faster and storage much smaller than with text formats.

How a Parquet file is organized

A Parquet file is split horizontally into row groups and vertically into column chunks. Each row group holds a block of rows, and within it each column is stored as a separate chunk made of pages, the smallest unit of encoding and compression. A footer at the end of the file holds the schema, the location of every chunk and per-chunk statistics.

UnitContainsTypical size
Row groupA horizontal slice of rowsOften 128 MB or a fixed row count, set by the writer
Column chunkOne column’s data within a row groupVaries with column width
PageEncoded and compressed valuesAbout 1 MB by default
FooterSchema, offsets and statisticsKilobytes to a few megabytes
Structural units of a Parquet file

Because readers start with the footer, an engine can plan the read without scanning the data. It fetches only the column chunks a query references, which is called column projection, and skips whole row groups whose statistics show they cannot match a filter, known as predicate pushdown.

Row group size is a trade-off. Larger row groups compress better and reduce metadata, while smaller row groups allow finer skipping and more parallel readers. Optional page indexes and Bloom filters in newer writers refine skipping further, letting readers avoid individual pages or rule out values that min and max statistics cannot exclude.

Encoding, compression and types

Storing one column at a time puts similar values next to each other, which makes them highly compressible. Parquet first applies a lightweight encoding, then an optional general-purpose compression codec to each page.

TechniqueKindWorks best for
Dictionary encodingEncodingColumns with few distinct values, such as country codes
Run-length encodingEncodingLong runs of repeated values and definition levels
Delta encodingEncodingSorted integers and timestamps
SnappyCompression codecFast reads with moderate compression
ZstandardCompression codecBetter ratio at similar read speed, tunable levels
GzipCompression codecHigh ratio with slower writes
Common encodings and codecs

Parquet has a small set of physical types, such as 32-bit and 64-bit integers, doubles and byte arrays, plus logical types that give them meaning, such as decimal, date, timestamp and string. Nested structures such as lists and maps are stored using repetition and definition levels, a technique adopted from the Dremel paper, which lets nested data remain columnar.

Parquet compared with other data formats

Parquet is optimized for write once, read many times analytical workloads. Other formats in the same family serve different purposes, and the right choice depends on access pattern rather than fashion.

FormatLayoutBest fit
ParquetColumnar, binary, compressed on diskAnalytical storage and data lakes
CSVRow-based plain textSimple exchange and spreadsheets
JSON and NDJSONRow-based text with nestingAPIs, logs and event streams
Apache ArrowColumnar, in memoryFast processing and exchange between tools
AvroRow-based binary with schemaStreaming and record-at-a-time writes
ORCColumnar binary on diskHive-centered analytical stacks
Parquet versus neighboring data formats

Parquet and Apache Arrow complement each other: Parquet is the compact on-disk format, and Arrow is the in-memory format that engines decode it into for vectorized processing. Converting between them is efficient because both are columnar.

Using Parquet effectively

Parquet performance depends heavily on how files are written. The same data can be fast or slow to query depending on file size, sort order and partitioning.

  • Aim for large files, typically hundreds of megabytes each, because thousands of tiny files multiply metadata and request overhead.
  • Sort or cluster data by frequently filtered columns so row group statistics become selective.
  • Partition directories by a low-cardinality column such as date, not by a high-cardinality identifier.
  • Choose Zstandard or Snappy according to whether storage or write speed matters more.
  • Keep schemas consistent and evolve them by adding optional columns rather than changing types.

Parquet files are immutable; updating a single row means rewriting a file. Table formats such as Apache Iceberg, Delta Lake and Apache Hudi add a transaction log on top of Parquet files to provide updates, deletes, snapshots and schema evolution.

Limitations and common mistakes

Parquet is a poor fit for frequent small writes, single-row lookups and human inspection. The table lists typical problems teams meet.

ProblemCauseRemedy
Small file problemStreaming jobs writing tiny filesCompact files on a schedule
No row group skippingUnsorted data spreads values evenlySort by common filter columns before writing
Schema conflictsSame column written with different typesEnforce schemas or use a table format
Timestamp shiftsMixed time zone and unit conventionsStandardize on UTC with explicit units
Slow point lookupsColumnar layout scans whole pagesUse a database or key-value store for lookups
Parquet problems and remedies

Compatibility can also vary. Older readers may not support newer logical types or encodings, so producers shared across many tools often stick to widely supported options.

The short version

Parquet stores a table column by column instead of row by row. Picture a filing cabinet where every drawer holds just one kind of information, all dates in one drawer and all prices in another, each tightly packed.

When someone asks for the average price, only the price drawer needs to be opened. That is why analysis on Parquet files is fast and the files are small, even though changing a single record is more work than in a spreadsheet.

Where it makes a difference

A mobile app company stores its event logs as compressed CSV files, about 2 TB per month, in cloud object storage. Analysts mostly query five of the sixty columns, filtered by date and event type, and each monthly report scans all the data and takes close to an hour.

The data team rewrites the logs into Parquet, partitioned by date, sorted by event type and compressed with Zstandard. Storage falls to a fraction of the original size, and the query engine now reads only the five needed columns and skips row groups for irrelevant event types. The same monthly report runs in a few minutes, and the cost of scanned data drops accordingly.