Definition · Row store, column store, bytes scannedA row store keeps the values of one row contiguously; a column store keeps the values of one column contiguously. Bytes scanned is the volume a query must read from storage.
For r rows of total width w across c columns, with j columns named and compression ratios ρ_row and ρ_col, the row store scans r·w/ρ_row and the column store scans r·(w/c)·j/ρ_col.
The row store's formula contains no j. That is the entire asymmetry: naming fewer columns cannot make a row store read less, because the unit it stores and the unit the device delivers are both the row. A query naming one column of twenty scans exactly as many bytes as a query naming all twenty.
10⁹ rows 200 B a row 20 columns, so 10 B a column 3 named
row store compresses 2× column store compresses 5× scan 1 GB/s
row store 10⁹ × 200 B ÷ 2 = 100.00 GB ÷ 1 GB/s = 100.00 s
column store 10⁹ × (3 × 10 B) ÷ 5 = 6.00 GB ÷ 1 GB/s = 6.00 s
ratio 16.67×
crossover columns × col ratio / row ratio = 20 × 5/2 = 50 columns
there are only 20, so no selection flips the scan here
A factor of 16.67 from a query that named a seventh of the columns is more than the seven you might expect, and the extra comes from the compression ratios: 10/3 from the columns and 5/2 from the compression, multiplied. That is why the ratio has to travel with the claim.
Where the answer reverses
Set the two byte counts equal and solve for the number of named columns: j* = c × ρ_col/ρ_row. At c = 20, ρ_col = 5 and ρ_row = 2 that is 50, which is past all twenty columns — so at these ratios no scan, however wide, makes the row store cheaper. Drop the columnar ratio to 2×, which is what happens when the columns hold high-cardinality values that do not compress, and the crossover falls to exactly 20: the two layouts tie on a query that reads everything.
Example · The query that actually flips itFetch one whole row by key. In a row store it is one page read: the row is contiguous, so the page holding any of its columns holds all of them. In a column store it is twenty page reads, one per column, because the twenty values live in twenty different places. That is a factor of twenty in the row store's favour on the same table, and it is not a scan at all.
So “columnar is always faster” is a claim about analytical scans wearing the clothes of a claim about storage. The honest form names the query shape: for scans over a few columns of many rows, columnar by a large factor; for retrieving whole rows one at a time, row store by a factor of the column count. A system doing both is a system that keeps the data twice, and that is a decision with a storage bill rather than a clever trick.
Two things held fixed here. The scan runs at 1 GB/s in both layouts, so nothing in the comparison is hiding a bandwidth difference — the whole effect is bytes. And the compression ratio is an input on this course rather than something derived: what a codec achieves on your data is measured, and the break-even between the ratio and the CPU it costs to decompress belongs to Scaling Laws and Cost.