Articles

Columnar vs. Row-Oriented Databases

Row-oriented databases store each record together on disk; columnar databases store each column together. The layout decides which workloads are fast.

The Lycoris Team The Lycoris Team · · 4 min read
An abstract illustration of stacked databases

Row-oriented storage keeps every field of a single record physically together on disk, so reading one record — every column of it — is a single sequential read. Columnar storage keeps every value of a single column together instead, across every record, so reading one column across many records means touching far less data, at the cost of making full-record reads more expensive. The same data, laid out differently, and the layout alone determines which workloads are fast.

What “layout” actually means on disk

Picture a table of orders with columns order_id, customer_id, amount, and status. A row-oriented engine physically stores (1, 501, 42.00, "shipped"), then (2, 502, 19.99, "pending"), and so on — each full row contiguous on disk. Fetching order #1’s full details is one read in one place.

A columnar engine instead stores all order_id values together, then all customer_id values together, then all amount values together, and so on. Fetching order #1’s full details now means touching four separate locations on disk — one per column. But computing the sum of amount across a million orders means reading only the amount column, contiguous and compact, instead of scanning every row and discarding three-quarters of each one along the way.

Why this maps directly onto OLTP vs. OLAP

This storage decision is the physical reason OLTP and OLAP workloads favor different database engines. OLTP workloads — placing an order, updating a customer’s address, checking an account balance — read and write whole records at a time, one record per operation. That’s exactly what row-oriented storage is built for: fetch or update one row, touch one contiguous chunk of disk.

OLAP workloads — “what’s our average order value by region this quarter” — read a handful of columns across millions of rows, and don’t care about most of the other columns in each row. Row-oriented storage would waste enormous effort reading data it’s about to discard; columnar storage reads exactly the columns the query needs and skips the rest. This is also why columnar formats compress dramatically better than row-oriented ones: a column of repeated status values like "shipped", "pending", "shipped" compresses far more efficiently sitting next to each other than interleaved with unrelated fields.

Where each shows up

Traditional relational databases used for application backends — the kind behind a typical REST API or ORM-driven app — are row-oriented, because the access pattern is overwhelmingly “fetch this one record” or “update this one record,” not “aggregate this column across everything.” PostgreSQL, in its default configuration, stores tables in row-oriented pages for exactly this reason.

Analytical and data-warehouse engines are typically columnar, because their entire purpose is aggregating and scanning across large numbers of records while only touching a few columns per query. This is also why a query that touches a specific, indexed subset of rows still benefits from indexing regardless of layout — an index narrows which rows or column values get scanned in the first place, while columnar vs. row-oriented storage determines how expensive scanning those values actually is once you get there.

Columnar vs. row-oriented storage

Row-orientedColumnar
Optimized forReading/writing whole recordsAggregating across few columns, many rows
Typical workloadOLTP — transactional appsOLAP — analytics, reporting, BI
CompressionModerate — mixed data types per blockHigh — like values stored contiguously
Full-record fetch costLow — one contiguous readHigher — one read per column
Column aggregation costHigh — scans and discards unused columnsLow — reads only the needed columns
Common examplesTraditional OLTP relational enginesData warehouse and analytical engines

Materialized views and the middle ground

Teams running an OLTP database rarely want to run heavy analytical queries directly against it — a large aggregation scan competes with the transactional workload for the same disk and cache resources the live application needs. A common pattern is keeping the row-oriented system for live transactions and periodically exporting data into a columnar system for reporting, or precomputing common aggregations as a materialized view so expensive scans don’t run on every request. Change data capture is the usual mechanism for keeping that columnar copy in sync with the transactional source without querying the live system directly for every analytical need.

Some newer engines blur the line — hybrid systems that store data in both layouts, or row-oriented systems with columnar extensions for specific tables — but the underlying trade-off doesn’t disappear: any given physical layout is still better at one access pattern than the other. Choosing a database, in other words, is really choosing which of these two costs you’re willing to pay more of.

The takeaway

Row-oriented and columnar storage aren’t competing feature sets — they’re the same data arranged for opposite access patterns. Row orientation wins when you need whole records fast, which is what transactional applications do constantly; columnar orientation wins when you need a few columns across huge numbers of records, which is what analytics does constantly. Picking between them (or running both, connected by a sync pipeline) comes down to which of those two shapes your actual queries look like.

The Lycoris Team The Lycoris Team · · 4 min read

Data Warehouse vs Data Lake: What's the Difference?

A data warehouse stores structured, pre-modeled data optimized for queries; a data lake stores raw data of any shape. When each one fits.

#Databases #Data Engineering #Backend
The Lycoris Team The Lycoris Team · · 4 min read

Star Schema vs Snowflake Schema: Which to Use

Star schema denormalizes dimensions into flat tables for fast queries; snowflake schema normalizes them to save space. How to choose for your warehouse.

#Databases #Data Engineering #Backend
Chisato Chisato · · 4 min read

Time-Series Databases Explained

A time-series database is optimized for timestamped data — metrics, sensor readings, prices. How it differs from general-purpose databases.

#Databases #Data Engineering #Backend