Lesson 02 Parquet & Columnar Storage
Theme:
Lesson 02 · Slide 1

Lesson 02 — Parquet & Columnar Storage

Why CSV was the wrong answer — and what to use instead.

Data Engineering Module 1
Lesson 02 · Slide 2

The five sins of CSV

Lesson 02 · Slide 3

Row-oriented vs columnar

CSV — row-oriented on disk

[r1_c1, r1_c2, r1_c3]
[r2_c1, r2_c2, r2_c3]
[r3_c1, r3_c2, r3_c3]
...

Each row is stored together. Reading one column means reading all of them.

Parquet — columnar on disk

[r1_c1, r2_c1, r3_c1]
[r1_c2, r2_c2, r3_c2]
[r1_c3, r2_c3, r3_c3]
...

Each column is stored together. Reading one column skips all the others.

Lesson 02 · Slide 4

Why columnar wins for analytics

Lesson 02 · Slide 5

What Parquet actually is

A file format developed at Twitter / Cloudera in 2013; an Apache project since 2015. It is the de facto storage layer of the modern lakehouse.

A Parquet file contains:

Lesson 02 · Slide 6

Apache Arrow — the in-memory cousin

Arrow is the columnar in-memory format. Parquet is the columnar on-disk format. They are designed to interoperate — reading a Parquet file produces an Arrow table in memory with near-zero copy overhead.

pyarrow is the Python implementation of both. When you call pq.read_table(), you get an Arrow table back. When you call pq.write_table(), Arrow columns are serialised to Parquet on disk.

You rarely need to think about Arrow directly — but knowing it exists explains why DuckDB, Pandas, Polars, and Spark all read Parquet without an intermediate format conversion.

Lesson 02 · Slide 7

Rewriting the L01 transform with pyarrow

import pyarrow as pa
import pyarrow.parquet as pq
import gzip, json, pathlib

def to_parquet(json_gz: pathlib.Path, parquet_out: pathlib.Path) -> None:
    rows = []
    with gzip.open(json_gz, "rt") as f:
        for line in f:
            ev = json.loads(line)
            rows.append({
                "type": ev["type"],
                "actor": ev["actor"]["login"],
                "repo":  ev["repo"]["name"],
                "created_at": ev["created_at"],
            })
    table = pa.Table.from_pylist(rows)
    pq.write_table(table, parquet_out, compression="snappy")

4 columns kept this time, not just type — and the file will still be smaller than the CSV.

Lesson 02 · Slide 8

Partitioning by event date

Partitioning splits one logical table across many physical directories. Layout:

data/parquet/
  date=2024-01-01/part-0.parquet
  date=2024-01-02/part-0.parquet
  ...

Queries that filter on date only open the directories that match — this is called partition pruning. A query for a single day touches 1/365 of the data, not all of it.

Lesson 02 · Slide 9

Side-by-side numbers (one hour of gharchive)

Format Size on disk Count PushEvents Count by type
Raw JSON.gz~50 MB~2.5 s~2.5 s
CSV (L01)~3 MB~0.4 s~0.4 s
Parquet (snappy)~1.5 MB~0.05 s~0.05 s
Parquet, partitioned by type~1.5 MB~0.002 s~0.05 s

Numbers are illustrative — run the lab and measure yours.

Lesson 02 · Slide 10

Reading Parquet with pandas

import pandas as pd
df = pd.read_parquet("data/parquet/date=2024-01-01/")
df["type"].value_counts().head(10)

read_parquet understands partitioned layouts natively — point it at the directory and it discovers all the part files automatically.

pandas delegates to pyarrow under the hood. The pyarrow engine is the default and the recommended choice; it handles all compression codecs and nested schemas.

Lesson 02 · Slide 11

Reading Parquet with DuckDB (preview of L09)

SELECT type, COUNT(*)
FROM 'data/parquet/date=2024-01-01/*.parquet'
GROUP BY type;

No database. No schema setup. No COPY command. Parquet on disk is the table. DuckDB reads it with full predicate pushdown and column pruning, then streams the result.

Lesson 02 · Slide 12

When NOT to use Parquet

  • Single-write append-only logs (use line-delimited JSON)
  • Ad-hoc CSV exports for humans to open in Excel
  • Tiny lookup tables under ~1 MB

Parquet shines at the scale where you cared about format choice. Below ~10 MB, almost any format is fine.

Lesson 02 · Slide 13

Pitfalls

Lesson 02 · Slide 14

Recap & what's next

Coming up: Lesson 03 — what to do when the schema drifts under your feet.
1 / ?