Data engineering·topic 4 of 8
Files, formats and table layers
Underneath every lakehouse is a folder of files, and most of its performance and most of its failures come from how those files are written. Knowing these words is the difference between tuning a query and guessing at one.
Read in order · tick what you already know
- 01
everything anyone might ever need is in a bucket as files, in whatever shape it arrived, and finding the useful part is your problem.
Data lake
- 02
the data is in typed, governed tables you query in SQL, and getting anything in means agreeing a schema first.
Data warehouse
- 03
the tables are open files in a bucket and you still get transactions, schema enforcement and a rollback.
Lakehouse
- 04
there are nine thousand tables in the bucket, four of them are used, and nobody knows which four.
Data swamp
- 05
there are no directories really, listing a prefix with a million keys is slow, and you cannot append to a file.
Object storage
- 06
the query reads three columns out of two hundred and only touches the bytes for those three.
Columnar format
- 07
the whole record is written together, so appending one event is cheap and reading one field of a billion records is not.
Row-oriented format
- 08
the files are columnar with statistics in the footer, so the engine can skip whole chunks without reading them.
Parquet
- 09
the tables are in the other columnar format, the one that came out of the Hive world, with stripes instead of row groups.
ORC
- 10
each message carries a schema id rather than field names, and adding an optional field does not break the consumers already running.
Avro
- 11
the file is split into blocks of a hundred and twenty-eight megabytes, each with its own min and max per column.
Row group
- 12
the column holds four distinct country names in eleven million rows, and the file stores small integers plus a lookup.
Dictionary encoding
- 13
someone switched the codec and the files got a third smaller while the queries got slightly slower to decode.
Compression codec
- 14
the where-clause is handed to the file reader, which uses the min and max in each chunk's footer to skip most of them unread.
Predicate pushdown
- 15
you replaced select star with the six columns you needed and the bytes scanned fell by ninety percent.
Projection pushdown
- 16
you filtered on the partition column and the engine opened four folders instead of nine hundred.
Partition pruning
- 17
the partition value is encoded in the folder name as dt=2026-01-14, and the column does not exist inside the files at all.
Hive-style partitioning
- 18
a streaming job wrote a file every ten seconds and now a single day's query opens eight thousand objects to read four hundred megabytes.
Small files problem
- 19
a maintenance job rewrites thousands of small files into a few large sorted ones, and nothing about the table's contents changes.
Compaction
- 20
there is a metadata layer over the files that says exactly which files are in the table right now, so two writers no longer overwrite each other.
Open table format
- 21
the engine reads one metadata file listing the table's data files and their statistics, instead of listing a bucket prefix.
Manifest file
- 22
the table's partitioning was changed without rewriting any of the existing files, and old queries kept working.
Iceberg
- 23
there is a _delta_log folder of JSON commits next to the Parquet, and reading the table means replaying that log.
Delta Lake
- 24
the table is built for frequent upserts by key, keeping a log of changes beside the base files and merging them on read.
Hudi
- 25
updating one row rewrites the entire file that row lived in, so writes are slow and every read is as fast as a plain scan.
Copy-on-write table
- 26
the update is written as a small delta file and the reader merges it with the base file every time, until a compaction folds them together.
Merge-on-read table
- 27
you queried the table as it stood before this morning's bad run, without restoring anything.
Time travel
- 28
you deleted the rows a month ago and the bytes were still in the bucket, because the old snapshots still referenced them.
Snapshot expiry
- 29
the file was written as whatever the source sent and the shape is decided by the query that reads it, which is why two teams parse it differently.
Schema-on-read
- 30
the load rejected the file because a column changed type, and the bad data never got into the table.
Schema-on-write
- 31
the vendor added three columns and renamed one over the weekend, and nobody told anybody.
Schema drift
- 32
the warehouse queries files it does not own, so dropping the table leaves the data exactly where it was.
External table