dataarchitect.studio

Field Notes

Parquet vs ORC vs Avro: Which Data File Format, and When

Three formats, one recurring question: which file format should this data live in? The clean answer starts with a single split. Parquet and ORC are columnar — built for reading and analytics. Avro is row-based — built for writing, streaming, and moving data between systems. Get that axis right and the choice is nearly made; the Parquet-vs-ORC decision that remains is mostly about ecosystem, not capability. Here’s the full comparison and a decision rule you can apply without re-reading it.

The comparison, at a glance

  Parquet ORC Avro
Layout Columnar Columnar Row-based
Best for Analytics / reads Analytics / reads (Hive-centric) Streaming / writes / exchange
Compression Excellent (measured smallest) Excellent Moderate
Column-pruning reads Yes — fast Yes — fast No (reads whole rows)
Write speed Slower (columnar encode) Slower (columnar encode) Fast
Schema evolution Good Good Excellent — its signature strength
Ecosystem home Spark, cloud warehouses, lakehouse default Hive / Hadoop, Trino Kafka, streaming, RPC
Stores schema In file footer In file footer With the data, richly
Typical role Default analytical data files Analytical files in Hive stacks Event/message payloads, table metadata

Columnar vs row-based — the decision that drives everything

The split is physical. A columnar format (Parquet, ORC) stores all of column A together, then all of column B. A query touching two of fifty columns reads only those two, and columns of like values — all timestamps, all country codes — compress hard. That pruning effect is not a small one: measured on 3 million rows, reading 2 of 11 columns was 6.9× faster than reading all of them. That’s exactly the shape of an OLAP analytical scan, and it’s why both dominate the warehouse and lakehouse world.

A row-based format (Avro) stores each record whole: all of row 1’s fields together, then row 2. Writing an event is one contiguous append; reading one record back is cheap. But an analytical query that wants one column still has to read past every other field in every row — the opposite of what analytics wants. Avro’s home is therefore movement: the Kafka streaming ecosystem, event logs, and cross-system exchange, where records are written whole and schema evolution across producers and consumers is a first-class concern.

Columnar versus row-based file layout Two panels. Columnar formats Parquet and ORC store all values of one column together, so reading one column touches one stripe and like values compress hard, giving fast reads for analytics. Row-based Avro stores each record whole, so writing is one append and the schema travels with the data, giving fast writes for streaming and exchange. Columnar — Parquet / ORC all order_id ┃ all amount ┃ all ts read 1 column → touch 1 stripe like values → compress hard → fast reads, small size, analytics Row-based — Avro row1{all fields} ┃ row2{all fields} write a record → one append schema travels with the data → fast writes, streaming, exchange the layout is the whole argument: columnar optimizes reading a few columns, row-based optimizes writing and moving whole records
Choose the axis first — columnar for analytics, row-based for streaming — and the rest is ecosystem.

Parquet vs ORC: the narrower call

Once you’ve chosen columnar, Parquet vs ORC is a closer, more ecosystem-driven decision. Both store the schema in a file footer, both prune columns and skip data using embedded statistics, both compress excellently. The practical differences:

  • Parquet is the default of the modern data stack — Spark, the cloud warehouses, dbt, and every open table format reach for it first. If you want the path of least resistance and maximum interoperability, it’s Parquet.
  • ORC grew up in the Hive/Hadoop world and has mature ACID support within Hive. It remains the natural choice where a Hive- or Trino-centric stack already favours it.

A correction. An earlier version of this essay said ORC “often edges Parquet on compression ratio,” which is the conventional claim. I then benchmarked it and got the opposite result: at matched codecs on a realistic table, Parquet was 23–26% smaller. That was one dataset and pyarrow’s ORC writer at defaults, so it doesn’t settle the question everywhere — but it’s enough that I no longer state the compression advantage as fact. Measure it on your data before it decides anything.

For a greenfield lakehouse, Parquet is the safe default and ORC is a deliberate, situational choice — not a mistake, just one you should be able to justify.

The decision rule

Is the workload read-heavy analytics (scan columns, aggregate)?
   → Columnar.
       On a modern / cloud / lakehouse stack?      → Parquet
       Deep in Hive/Hadoop, or compression-critical? → ORC

Is the workload write-heavy / streaming / cross-system exchange,
or is schema evolution across producers the hard part?
   → Row-based → Avro

The twist: it’s rarely either/or

Mature stacks use all three, each where it fits. Avro carries events through Kafka streaming pipelines; those events land and are rewritten as Parquet for the analytical layer; a Hive-heavy corner might keep ORC. And here’s the detail that surprises people: even when your data files are Parquet, the table format’s own metadata manifests are often Avro — because manifest files are written whole and benefit from exactly Avro’s row-based, schema-evolvable design. The formats aren’t rivals fighting for one slot; they’re specialists, and a well-built platform hires all three. The skill is matching the format to the layer — which, one rung up, is the same instinct behind choosing a table format over bare files in the first place.

Common questions

What is the difference between Parquet, ORC, and Avro?

Parquet and ORC are columnar formats — they store all of one column together, which makes analytical queries that read a few columns fast and highly compressible. Avro is row-based — it stores whole records together, which makes it fast to write and ideal for streaming and data exchange. Columnar wins for reads and analytics; row-based wins for writes, streaming, and schema evolution.

Which is better, Parquet or ORC?

Both are columnar and both are excellent; the difference is ecosystem more than capability. Parquet is the de facto default across Spark, the cloud warehouses, and most of the modern data stack, and it's what open table formats reach for. ORC has deep roots in the Hive/Hadoop world, including ACID support there. ORC is often said to compress better, but a benchmark on this site found Parquet 23-26% smaller at matched codecs, so treat that claim as something to measure rather than assume. For a new lakehouse, Parquet is the safe default.

When should I use Avro instead of Parquet?

Use Avro when writes dominate reads: streaming pipelines (it's the standard in the Kafka ecosystem), event logs, and any place records are written whole and often, or where schema evolution across systems matters. Avro's row-based layout and rich schema-evolution support make it ideal for moving data; its weakness is analytical queries, where columnar Parquet or ORC is far faster.

Do open table formats like Iceberg use Parquet, ORC, or Avro?

All three are supported as underlying data files by Apache Iceberg, and the choice is a per-table property — but Parquet is the overwhelming default for analytical tables. Interestingly, Avro often appears inside the table format's own metadata layer even when the data files are Parquet, because manifest files are written whole and benefit from Avro's row-based, evolvable format.