Choose a layout
Data is about to be stored, as database pages, files in a lake, or values in a key-value store. Laying it out row by row makes fetching one record cheap; column by column makes scanning a few fields cheap and compression strong; PAX stores columns inside groups of rows to get some of both. Which layout fits how this data is read and written?
You will end with a physical layout for the data, and the measurements that justify it.
Stop at the first answer that decides it.
Decide
Is the smallest efficient read on your storage 1 MB or more?
True for object storage and every cloud warehouse; false for local SSDs and database pages.
Why
When every read must be large to be efficient, PAX is the only layout whose unit matches the medium. What remains is tuning the row-group size and the encodings.
Is the data read less often than it is written?
Why
Below about one read per write, how records sit next to each other hardly affects anything: you are limited by writes, and the real decision is how changes are written.
Are parts of rows frequently updated in place?
YesRow layout
NoGo to 5
Why
An encoded column block is the unit of update, so changing one field means rewriting the block. Frequent partial-row updates force a row layout, or push you into writing changes separately and merging them on read.
How many rows does a typical query read?
Why
For a single row, reading a whole column block per field wastes almost all of each read. For millions, columnar compression and vectorized processing dominate regardless of anything else.
What share of the columns does a typical query touch?
Why
A query touching most columns gains nothing from reading them separately; one touching a tenth reads a tenth of the bytes. PAX is also the right default when you do not know.
Where you can land
PAX (columns within row groups)
Use it when reads must be large, or queries touch a middling share of columns.
As in Parquet and ORC row groups. What it costs: an update rewrites a whole row group, and the row-group size must be tuned to the medium.
Columnar
Use it when queries read many rows and few columns.
What it costs: reconstructing one full row touches every column; updates rewrite encoded blocks.
Row layout
Use it when queries read single rows, most columns, or update parts of rows in place.
What it costs: scans read every column, and compression is weaker.
Key-value
Use it when the value cannot be described by a schema.
What it costs: the store cannot look inside values, so all access goes through the key; budget for key design, which you have just taken on.