Module: Foundations | Duration: 8 min read | Lesson: 1 of 17
Maya just joined TheWorldShop, a global marketplace that sells everything from groceries to electronics. On her first day the CFO complains that the daily revenue dashboard takes seven minutes and costs $40 every refresh. Maya opens the warehouse and finds four years of orders sitting in CSV. The dashboard needs one column. Every query reads all hundred. Why does CSV make you pay for data you never touch, and what flips that?
2. Concept Explanation
Parquet stores each column of a table in its own contiguous byte range instead of storing each row together. That single decision means a query touching 3 columns out of 100 reads roughly 3% of the file's data bytes, not 100%. The tradeoff is write complexity and a random-access penalty. Parquet is built for analytical reads, not point lookups or frequent small updates.
A row-oriented format (CSV, Avro) lays data out like this:
To compute SUM(revenue) you read every field of every row to reach the revenue bytes scattered through the file. On a 10-column table with a billion rows, that's about 10x more data than you need.
Parquet's columnar layout groups by column instead:
SUM(revenue) seeks straight to the revenue column chunk in each row group and reads only those bytes. Min/max statistics let the engine skip whole row groups where no matching value can exist.
Three more wins follow from the layout:
Encoding. Consecutive values in a column share a type and often share prefixes or low cardinality. Dictionary, RLE, and delta encodings exploit that. They can't exploit it across interleaved row bytes.
Compression. Compressors like Snappy and Zstd work on blocks of similar data. A column of INT32 timestamps compresses far better than a row of mixed types.
Vectorized execution. CPUs process columnar arrays with SIMD instructions. A tight loop over float64[N] runs vectorized. A loop that chases struct fields does not.
The top-level structure is described by FileMetaData in parquet.thrift:
3. Worked Example
Reading 2 columns out of 20 only touches the byte ranges for those two. The other 18 column chunks are never read off disk.
Aha: Parquet's read savings come from what it doesn't read. The moment you write SELECT * at scale you pay the full write cost of buffering row groups and get none of the column-skipping benefit. Columnar storage rewards selectivity, and punishes you for asking for everything.
4. Your Turn
Exercise: TheWorldShop's orders table has 100 columns and a billion rows. The revenue dashboard reads 3 columns. Reason about the I/O before you measure it.
- Roughly what fraction of the data bytes does the dashboard read from Parquet versus from CSV?
- Name one query shape where Parquet would read more than the CSV equivalent.
- The team also wants to fetch a single full order by
order_idthousands of times per second. Is Parquet the right format for that path? Why or why not?
5. Real-World Application
Every large analytics stack leans on this layout. BigQuery, Snowflake, Athena, Spark, and DuckDB all read columnar data so a dashboard that touches a few columns scans a few columns. When TheWorldShop moves its CSV exports to Parquet, the seven-minute revenue dashboard drops to seconds because it stops reading 97 columns it never displays. The same move cuts the per-query scan cost on systems billed by bytes scanned, which is why the CFO notices it on the invoice as well as the wall clock.
6. Recap + Bridge
Parquet groups data by column so selective queries read selective bytes, and that one decision unlocks encoding, compression, and vectorized reads. It pays off when queries are column-selective and costs you when you ask for whole rows. Next we crack the file open and look at the containers inside it: row groups, column chunks, and pages.