Parquet File Format
Overview mental model for Parquet: why it exists, row-based vs column-based contrast, file layout, row groups, column chunks, pages, footer metadata, encoding, compression, and where it sits in lakehouse storage.
Parquet File Format: physical layout cho analytics workload
Vì sao cần Parquet?
Data platform thường có workload kiểu:
ghi theo batch / append nhiều file
đọc lại rất nhiều lần bằng Spark / Trino / DuckDB / BI
query thường scan nhiều rows nhưng chỉ cần một số columnsNếu lưu bằng CSV/JSON, engine phải parse text, infer/đọc schema yếu, và thường kéo theo nhiều data không cần thiết. Parquet sinh ra để trả lời một nhu cầu cụ thể hơn:
Làm sao lưu dữ liệu dạng bảng trên distributed storage sao cho analytics engine đọc ít bytes hơn, decode ít hơn, và có metadata để prune trước khi scan data thật?
Parquet là file format, không phải table format. Nó mô tả layout bên trong từng file. Delta Lake/Iceberg/Hudi có thể dùng Parquet làm data file, rồi thêm metadata/transaction/snapshot ở tầng table bên ngoài.
Logical table vs physical file layout
Một table nhìn ở SQL level có vẻ rất đơn giản:
| user_id | country | event_date | amount |
|---|---|---|---|
| 1 | VN | 2026-06-01 | 100 |
| 2 | US | 2026-06-01 | 200 |
| 3 | VN | 2026-06-02 | 300 |
Nhưng khi persist xuống file, câu hỏi quan trọng là:
Các values được đặt cạnh nhau theo row, theo column, hay theo một layout hybrid nào đó?
Row-based format
Row-based layout đặt các field của cùng một record gần nhau:
[user_id=1, country=VN, event_date=2026-06-01, amount=100]
[user_id=2, country=US, event_date=2026-06-01, amount=200]
[user_id=3, country=VN, event_date=2026-06-02, amount=300]Nó hợp với mental model “mỗi lần đọc/ghi là một event/record”. Ví dụ:
- application log;
- message/event payload;
- streaming record;
- row-level serialization.
Nhưng với analytics query:
SELECT sum(amount)
FROM events
WHERE country = 'VN';engine chỉ cần hai cột country và amount. Nếu file layout ép engine đọc từng row nguyên vẹn, nó dễ đọc dư user_id, event_date, payload, v.v.
Column-based format
Column-based layout đặt values của cùng một column gần nhau:
user_id: [1, 2, 3]
country: [VN, US, VN]
event_date: [2026-06-01, 2026-06-01, 2026-06-02]
amount: [100, 200, 300]Điểm mạnh:
| Mechanism | Vì sao có lợi cho analytics? |
|---|---|
| Column pruning | Query cần cột nào thì đọc cột đó, tránh kéo theo wide columns không dùng. |
| Better compression | Values cùng type/domain nằm cạnh nhau nên dictionary/RLE/delta/compression hiệu quả hơn. |
| Vectorized scan | Engine có thể decode/process theo batches của một column thay vì từng object row. |
| Metadata pruning | Format có thể giữ statistics theo block/row group/page để skip data chắc chắn không match. |
Columnar không phải magic. Nếu data layout trộn lung tung, stats quá rộng, file quá nhỏ/quá nhiều, hoặc query filter không align với layout, Parquet vẫn có thể scan rất nhiều bytes.
Parquet không phải “một cục column cho cả file”
Parquet là columnar, nhưng nó không đơn giản là:
whole file user_id column
whole file country column
whole file amount columnNó chia file thành row groups. Mỗi row group chứa một batch rows. Bên trong mỗi row group, data được lưu theo column chunks.
Parquet file
├── Row group 1
│ ├── Column chunk: user_id
│ ├── Column chunk: country
│ ├── Column chunk: event_date
│ └── Column chunk: amount
├── Row group 2
│ ├── Column chunk: user_id
│ ├── Column chunk: country
│ ├── Column chunk: event_date
│ └── Column chunk: amount
└── Footer metadataMental model:
Parquet = horizontally split into row groups,
then vertically stored as column chunks inside each row group.Vì vậy row group không làm Parquet thành row-based. Nó là đơn vị batch/metadata/parallelism/pruning. Bên trong row group vẫn là columnar.
Các concept chính trong Parquet
| Concept | Mental model | Nó giúp gì? |
|---|---|---|
| File | Một physical object trên HDFS/S3/local disk | Đơn vị storage/list/read ở hệ thống bên dưới |
| Row group | Batch rows lớn trong file | Đơn vị parallelism, pruning, buffering |
| Column chunk | Data của một column trong một row group | Column pruning: đọc cột cần thiết |
| Page | Block nhỏ hơn trong column chunk | Encoding/compression/page-level read |
| Encoding | Cách biểu diễn values trước compression | Dictionary, RLE, delta giúp giảm size/CPU/I/O |
| Compression | Nén bytes sau encoding | Giảm storage và network/disk I/O |
| Footer | Metadata cuối file | Schema, row groups, column chunks, stats, offsets |
| Statistics | min/max/null_count/distinct-ish tùy support | Predicate pruning: skip row group/page/file |
Read path simplified
Ví dụ query:
SELECT amount
FROM events
WHERE event_date = '2026-06-27'
AND country = 'VN';Engine có thể:
- đọc footer để biết schema, row group, offset, stats;
- bỏ qua row group có
event_date min/maxkhông overlap ngày cần query; - chỉ đọc column chunks liên quan tới
event_date,country,amount; - decompress/decode phần còn lại.
Write path simplified
incoming rows
↓
buffer thành row group
↓
tách theo column chunks
↓
encode values
↓
compress pages
↓
tính statistics
↓
ghi data pages + footer metadataParquet thường đắt hơn khi write so với dump row/text đơn giản, nhưng trade-off là query sau đó đọc rẻ hơn nhiều.
Parquet rất hợp với analytics/lakehouse vì dữ liệu thường được ghi theo batch/append rồi đọc lại nhiều lần. Chi phí encode/compress/statistics ở write path được trả để giảm scan I/O, storage size, network, và CPU ở read path.
Parquet trong lakehouse
Trong lakehouse, Parquet thường là data-file layer:
Table format không thay thế Parquet. Nó quản lý tập nhiều Parquet files như một table có snapshot, transaction, schema evolution, partition evolution, manifests/logs, v.v.
My Summary
Parquet nên được hiểu như một physical layout cho analytics:
row-based format: đọc/ghi tiện theo record
column-based format: scan analytics tốt hơn vì đọc theo cột
Parquet: columnar + row groups + pages + footer metadata + encoding/compression/statisticsĐiểm quan trọng nhất với data platform không phải “Parquet nhanh”, mà là:
Parquet tạo điều kiện để engine đọc ít bytes hơn, nhưng hiệu quả thật phụ thuộc vào layout, file size, row group size, statistics quality, partitioning/clustering, và table-format metadata ở tầng trên.
Next notes
- Parquet Row Group and Statistics
- Later: Parquet encoding/compression, schema evolution, page index/bloom filter, and how Delta/Iceberg consume Parquet metadata.