OLTP vs OLAP is the most useful split to understand before choosing a database. OLTP (online transaction processing) systems handle a constant stream of small, short transactions that each touch a few rows, such as placing an order or withdrawing cash. OLAP (online analytical processing) systems run fewer but much larger queries that scan millions of rows to answer questions like "revenue by region per month". The two workloads want opposite things from storage, which is why most companies end up running both.
This guide first sorts the main database families (relational, object-relational, object-oriented and NoSQL), then compares OLTP and OLAP with real systems and tools, explains the row-oriented and column-oriented storage behind them, and ends with a practical way to choose.
Database families at a glance
Before the workload question, there's the data model question: how the database represents your data.
| Family | Data model | Examples | Typical use |
|---|---|---|---|
| RDBMS | Tables of rows, related by keys, queried with SQL | PostgreSQL, MySQL, Oracle Database, Microsoft SQL Server | Membership systems, e-commerce, course registration, most business apps |
| ORDBMS | Relational plus custom types, arrays, inheritance, extensible types | PostgreSQL, Oracle Database | GIS and maps, JSON documents, complex domain types |
| OODBMS | Objects stored directly, with references between them | ObjectDB, GemStone/S | Niche systems with deep object graphs |
| NoSQL | Several non-relational models (below) | MongoDB, Redis, Cassandra, Neo4j | Flexible schemas, extreme scale, special access patterns |
Relational (RDBMS)
Data lives in tables with a fixed schema. Relationships are expressed with keys and joins, and integrity with constraints. Relational databases give you ACID transactions, a mature query optimizer, and decades of tooling. For a new business application, a relational database is the default choice unless you have a clear reason otherwise.
Object-relational (ORDBMS)
An object-relational database is a relational database that also understands richer types. PostgreSQL is the best-known example. You can define composite types, store arrays and jsonb, and add new data types and index methods through extensions such as PostGIS:
CREATE TYPE address AS (street text, city text, postcode text);
CREATE TABLE stores (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL,
addr address,
tags text[],
attrs jsonb
);
SELECT name, (addr).city
FROM stores
WHERE '24h' = ANY (tags)
AND attrs @> '{"parking": true}';In practice the line between RDBMS and ORDBMS has blurred. MySQL, SQL Server and Oracle all support JSON today. The label matters less than whether the specific features you need are there.
Object-oriented (OODBMS)
An object database stores application objects as they are, including references between them, without mapping them to tables. ObjectDB (for Java) and GemStone/S (for Smalltalk) are examples. db4o was another, but it has been discontinued. OODBMSs remain a niche: ORMs on top of relational databases took over most of the job, and relational databases offer better ad-hoc querying and tooling.
NoSQL
NoSQL covers several different models:
- Document (MongoDB, CouchDB): JSON-like documents with flexible structure. Good when each record is naturally a self-contained document.
- Key-value (Redis, Amazon DynamoDB): get and set by key, very fast. Common for caching, sessions and counters, as covered in Redis caching, data structures and persistence.
- Wide-column (Apache Cassandra, ScyllaDB): rows partitioned across many nodes, designed for heavy write throughput and access by partition key.
- Graph (Neo4j): nodes and relationships as first-class data, for queries that follow many hops. See optimizing graph workloads.
NoSQL systems usually trade some of the relational guarantees, such as multi-row transactions, joins or strict schemas, for scale or flexibility. Many now offer transactions within limits, so check the specific product rather than assuming.
OLTP vs OLAP: the core difference
Data model aside, the workload decides a great deal about the database you need.
| OLTP | OLAP | |
|---|---|---|
| Purpose | Run the business | Analyze the business |
| Typical operation | Insert, update, or read one record by key | Scan and aggregate millions of rows |
| Rows touched per query | A few | Millions to billions |
| Columns touched | Most of the row | A few of many |
| Latency target | Milliseconds | Seconds to minutes is acceptable |
| Concurrency | Thousands of small transactions | Fewer, heavier queries |
| Schema | Normalized, many related tables | Denormalized star or snowflake schema |
| Storage layout | Row-oriented | Column-oriented |
| Data freshness | Current, second by second | Loaded in batches or streamed with some delay |
| Examples | PostgreSQL, MySQL, Oracle, SQL Server | BigQuery, Snowflake, Amazon Redshift, ClickHouse |
OLTP systems
OLTP is the database behind an ATM, a ticket booking system, an online store's checkout, or a core banking system. Every action is a short transaction:
BEGIN;
INSERT INTO orders (customer_id, amount, created_at)
VALUES ('C01', 500.00, now());
UPDATE inventory SET stock = stock - 1
WHERE sku = 'TSHIRT-M' AND stock > 0;
COMMIT;What matters here is correctness under concurrency and consistently low latency. Two customers must not buy the last T-shirt, and a transfer must never be half applied. Those guarantees come from ACID transactions, explained with a bank-transfer example in ACID and MVCC explained. OLTP queries find rows through indexes on keys, so good index design matters far more than raw scan speed.
OLAP systems
OLAP is the data warehouse behind an executive dashboard, monthly sales reports by region, or customer behavior analysis. A typical query reads a large slice of history and aggregates it:
SELECT date_trunc('month', s.sold_at) AS month,
c.region,
sum(s.amount) AS revenue
FROM fact_sales s
JOIN dim_customer c ON c.customer_key = s.customer_key
WHERE s.sold_at >= date '2026-01-01'
GROUP BY 1, 2
ORDER BY 1, 2;Analytical schemas are usually a star schema: a large fact table of events (sales, clicks, payments) surrounded by smaller dimension tables (customer, product, date). Redundancy is accepted because it makes queries simpler and faster.
Common OLAP technologies:
- Cloud warehouses: Google BigQuery, Snowflake, Amazon Redshift.
- Real-time analytical databases: ClickHouse, Apache Druid, Apache Pinot, for dashboards over fresh event data.
- Embedded analytics: DuckDB, for analyzing files and datasets on one machine.
- OLAP cubes: Microsoft SQL Server Analysis Services, which pre-aggregates data into multidimensional models for BI tools.
Row-oriented vs column-oriented storage
The biggest technical difference between OLTP and OLAP databases is how they lay data out on disk. Take a table sales(order_id, customer_id, amount, created_at).
A row-oriented database stores each row's values together:
page 1: [101, C01, 500, 2026-04-01] [102, C02, 700, 2026-04-01] [103, C01, 200, 2026-04-02] ...A column-oriented database stores each column's values together:
order_id: 101, 102, 103, ...
customer_id: C01, C02, C01, ...
amount: 500, 700, 200, ...
created_at: 2026-04-01, 2026-04-01, 2026-04-02, ...Row storage suits OLTP. Inserting an order, updating one customer's status or fetching order 102 by ID all read or write one row, and that row sits in one place. PostgreSQL, MySQL and most transactional databases work this way, and PostgreSQL storage internals shows how those rows are packed into 8KB pages.
Column storage suits OLAP. SELECT sum(amount) FROM sales WHERE created_at >= ... only needs two columns. A column store reads just amount and created_at and skips the rest. With a table of 50 columns, that can mean reading a small fraction of the bytes. Values in one column also have the same type and often repeat, so they compress very well with techniques like dictionary and run-length encoding. Many column engines also process values in batches (vectorized execution), which uses the CPU efficiently.
The trade-off runs the other way for writes. Inserting or updating a single row in a column store touches every column's storage, so these systems prefer loading data in large batches.
Moving data from OLTP to OLAP
Most organizations don't pick one. The OLTP database runs the application, and data is copied into an OLAP system for analysis:
- Batch ETL or ELT. A scheduled job extracts changed rows, loads them into the warehouse, and transforms them there. Simple, but data is hours old.
- Change data capture (CDC). A tool such as Debezium reads the database's change log (PostgreSQL's WAL, MySQL's binlog) and streams every change, often through Kafka, into the warehouse within seconds or minutes.
- Read replicas. For smaller analytical needs, run reports against a replica so heavy queries don't slow down the primary.
Keeping heavy analytical queries off the OLTP primary is the key point. A single long report can compete for CPU and I/O with checkout traffic.
Can one database do both?
To a point. PostgreSQL handles moderate analytics well if you help it:
-- BRIN index: tiny, effective on append-only time columns
CREATE INDEX orders_created_brin ON orders USING brin (created_at);
-- pre-aggregate a heavy report
CREATE MATERIALIZED VIEW monthly_revenue AS
SELECT date_trunc('month', o.created_at) AS month,
c.region,
sum(o.amount) AS revenue
FROM orders o
JOIN customers c ON c.id = o.customer_id
GROUP BY 1, 2;
CREATE UNIQUE INDEX ON monthly_revenue (month, region);
REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_revenue;Table partitioning by date, parallel query and extensions that add columnar storage push this further. Some databases, often called HTAP (hybrid transactional/analytical processing), such as TiDB and SingleStore, keep both row and column copies of data inside one system.
Past a certain data volume or query complexity, a dedicated OLAP system is simpler and cheaper than stretching the OLTP database.
How to choose a database
Ask these questions in order:
- What's the workload? Many small transactions (OLTP), large scans and aggregations (OLAP), or both?
- What shape is the data? Tables with relationships point to relational. Self-contained documents, key lookups, or deep graphs may point to a NoSQL family.
- How strict must correctness be? Money, inventory and bookings need multi-row ACID transactions.
- What scale do you need, realistically? A single well-tuned PostgreSQL server handles more than most applications ever need. Don't design for traffic you don't have.
- What can your team operate? Backups, upgrades, monitoring and failover matter as much as features.
For most new products, a sensible default is a relational OLTP database such as PostgreSQL, Redis for caching if needed, and a warehouse or ClickHouse added once analytics outgrow read replicas.
FAQ
What is the main difference between OLTP and OLAP?
OLTP runs many small, fast transactions that read and write a few rows, and powers the application. OLAP runs fewer, large queries that scan and aggregate lots of historical data, and powers reporting and analysis.
Is PostgreSQL OLTP or OLAP?
PostgreSQL is primarily an OLTP database with row-oriented storage. It handles moderate analytics with indexes, partitioning, materialized views and parallel query, but dedicated column stores are faster for large analytical workloads.
Is a data warehouse OLAP?
Yes. A data warehouse is the typical OLAP system: it stores integrated historical data from operational databases, organized for analysis rather than for transactions.
Why are column-oriented databases faster for analytics?
They read only the columns a query needs, compress similar values well, and process values in batches. Analytical queries usually touch a few columns across many rows, which is the case column storage is built for.
Is PostgreSQL an object-relational database?
Yes. It is usually described as an object-relational database because it supports custom and composite types, arrays, table inheritance and extensible data types and indexes.
A short decision checklist
- Start with the workload: transactions, analytics, or both.
- Use a relational OLTP database for the core application unless you have a concrete reason not to.
- Move analytics off the primary: first a read replica, then a warehouse fed by ETL or CDC.
- Pick column-oriented storage for large scans and aggregates, row-oriented storage for frequent single-row reads and writes.
- Choose NoSQL for a specific access pattern it serves well, not by default.
If you're weighing these options for a real system, Vectorkub can help design the data architecture.
