Optimal file size: a multiple of F × b
What file size minimizes scan time, and what stops files from growing larger?
Let us derive the best file size from first principles.
A scan reads D bytes of data, split across N files. Each file costs a fixed per-object cost F: the request round trip, reading the file footer (the metadata at the end of a Parquet file that describes its layout), and a metadata entry. On an object store F is about 20-50 ms and it does not shrink when the file is smaller. Then the data itself streams at bandwidth B. So the total cost is roughly:
- files the scan opens
- fixed per-object cost (round trip, footer, metadata), 20–50 ms on an object store
- how many files are fetched at once
- bytes of data read
- aggregate read bandwidth
Data table
| File size | Scan time |
|---|---|
| 97.7 KB | 166 s |
| 110 KB | 149 s |
| 123 KB | 134 s |
| 138 KB | 121 s |
| 155 KB | 109 s |
| 174 KB | 97.9 s |
| 195 KB | 88.3 s |
| 219 KB | 79.8 s |
| 245 KB | 72.2 s |
| 275 KB | 65.4 s |
| 309 KB | 59.4 s |
| 346 KB | 54 s |
| 389 KB | 49.2 s |
| 436 KB | 45 s |
| 489 KB | 41.2 s |
| 549 KB | 37.8 s |
| 616 KB | 34.8 s |
| 691 KB | 32.1 s |
| 776 KB | 29.7 s |
| 870 KB | 27.5 s |
| 977 KB | 25.6 s |
| 1.07 MB | 23.9 s |
| 1.2 MB | 22.4 s |
| 1.35 MB | 21.1 s |
| 1.51 MB | 19.9 s |
| 1.7 MB | 18.8 s |
| 1.9 MB | 17.8 s |
| 2.14 MB | 17 s |
| 2.4 MB | 16.2 s |
| 2.69 MB | 15.5 s |
| 3.02 MB | 14.9 s |
| 3.38 MB | 14.4 s |
| 3.8 MB | 13.9 s |
| 4.26 MB | 13.5 s |
| 4.78 MB | 13.1 s |
| 5.36 MB | 12.8 s |
| 6.02 MB | 12.5 s |
| 6.75 MB | 12.2 s |
| 7.58 MB | 12 s |
| 8.5 MB | 11.8 s |
| 9.54 MB | 11.6 s |
| 10.7 MB | 11.4 s |
| 12 MB | 11.2 s |
| 13.5 MB | 11.1 s |
| 15.1 MB | 11 s |
| 17 MB | 10.9 s |
| 19 MB | 10.8 s |
| 21.4 MB | 10.7 s |
| 24 MB | 10.6 s |
| 26.9 MB | 10.6 s |
| 30.2 MB | 10.5 s |
| 33.8 MB | 10.4 s |
| 38 MB | 10.4 s |
| 42.6 MB | 10.3 s |
| 47.8 MB | 10.3 s |
| 53.6 MB | 10.3 s |
| 60.2 MB | 10.2 s |
| 67.5 MB | 10.2 s |
| 75.8 MB | 10.2 s |
| 85 MB | 10.2 s |
| 95.4 MB | 10.2 s |
| 107 MB | 10.1 s |
| 120 MB | 10.1 s |
| 135 MB | 10.1 s |
| 151 MB | 10.1 s |
| 170 MB | 10.1 s |
| 190 MB | 10.1 s |
| 214 MB | 10.1 s |
| 240 MB | 10.1 s |
| 269 MB | 10.1 s |
| 302 MB | 10 s |
| 338 MB | 10 s |
| 380 MB | 10 s |
| 426 MB | 10 s |
| 478 MB | 10 s |
| 536 MB | 10 s |
| 602 MB | 10 s |
| 675 MB | 10 s |
| 758 MB | 10 s |
| 850 MB | 10 s |
| 954 MB | 10 s |
where P is the parallelism (how many files are fetched at once). The first term is overhead. For one file of size s streamed at rate b per connection, the share of time lost to overhead is:
- F (per-file cost)
- — the setup cost paid for each operation, whatever its size
- b (stream rate)
- — bytes per second once data streams
- s (file size)
- — bytes moved per operation
With F = 50 ms and b = 100 MB/s, a 5 MB file loses half its time to overhead, a 50 MB file about 9%, a 500 MB file about 1%. This is the natural transfer size of the medium, the fixed cost divided out.
Returns diminish quickly. After about 100 MB there is little more to gain. This is the whole reason the industry's target file sizes cluster in the 128 MB to 1 GB band. Nobody chose that number. It is a multiple of F × b (5 MB here), set by how much overhead you accept.
Why not make files even larger?
Because skipping, parallelism and copy-on-write all work per file, a file can also be too large: a file that matches every predicate is always read, too few files leave workers idle, and a one-row update rewrites the whole file. Where those bounds sit is a layout decision; maintenance restores files toward the size it chose.
A correction about small files and money
A common claim says small files are expensive "because of per-GET charges." In dollar terms this is mostly wrong. Worked example: a 1 TB scan with 10 MB files is 1,000,000 MB / 10 MB = 100,000 GET requests. At a typical price of about $0.0004 per 1,000 GETs, that is about $0.04: a few cents. The real damage is latency and, more importantly, planning cost, which we meet in Reclamation under manifest rewriting. Which frame applies depends on what you count: per query the request fees are a few cents, but summed over a year of a fleet's queries they can outgrow the storage bill (see Target file size).