Definition
- OLTP – Online Transaction Processing: systems that handle many small, fast, concurrent read-write transactions using normalized schemas and row-oriented storage.
- OLAP – Online Analytical Processing: systems that handle complex, long-running queries over large volumes of historical data using denormalized star or snowflake schemas and column-oriented storage.
- Normalized schema – data split into many related tables so each fact lives in one place, preventing update anomalies.
- Star schema – a central fact table of events surrounded by dimension tables for lookup attributes.
- Row-oriented storage – all columns of a row stored together, ideal for point lookups.
- Column-oriented storage – all values of one column stored together, ideal for aggregating a few columns across billions of rows.
The National Bank of India's teller counter is OLTP: hundreds of small, quick actions a second, where Rajesh withdraws cash and Priya pays rent, each touching one or two accounts and needing to be instant and correct. The bank's research department is OLAP: an analyst asks "what was total spend per branch last quarter", a heavy question scanning millions of records. If you forced the analyst to run that giant report on the live teller system, every customer at the counter would be stuck waiting. So the bank copies data into a separate analytics system where big questions run without freezing the counter.
Understanding the Concepts
What is OLTP?
OLTP stands for Online Transaction Processing. These systems are tuned for a workload of many small transactions with strict latency and strong consistency. They use normalized schemas to avoid update anomalies, row-oriented storage for fast point lookups, and ACID transactions for correctness.
-- Typical OLTP: small, fast, one-row update
UPDATE accounts
SET balance = balance - 50000
WHERE account_id = 'SAV2001';
-- Runs thousands of times per second
-- Touches one row, completes in milliseconds
package com.bank.core;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class OLTPExample {
public static void main(String[] args) throws Exception {
String sql = "UPDATE accounts SET balance = balance - ? "
+ "WHERE account_id = ?";
try (Connection conn = DriverManager.getConnection(
"jdbc:postgresql://localhost/bankdb",
"app", "secret");
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setBigDecimal(1, new BigDecimal("50000"));
ps.setString(2, "SAV2001");
int rows = ps.executeUpdate();
System.out.println("Updated rows: " + rows);
}
}
}
Updated rows: 1
What is OLAP?
OLAP stands for Online Analytical Processing. These systems are tuned for a smaller number of very heavy queries scanning huge amounts of historical data. They use denormalized star or snowflake schemas with fact and dimension tables, and column-oriented storage so aggregations read only the columns they need.
-- Typical OLAP: massive scan-and-aggregate
SELECT d.branch_name,
SUM(f.amount) AS total_spend,
COUNT(*) AS txn_count
FROM fact_transactions f
JOIN dim_branch d ON f.branch_id = d.branch_id
WHERE f.quarter = 'Q3-2024'
GROUP BY d.branch_name
ORDER BY total_spend DESC;
branch_name | total_spend | txn_count
Mumbai Central | 45000000.00 | 125000
Delhi Main | 38000000.00 | 98000
Bangalore IT | 32000000.00 | 87000
How is OLTP different from OLAP?
| Aspect | OLTP | OLAP |
|---|---|---|
| Workload | Many small, fast transactions | Few heavy, long scans |
| Schema | Normalized (3NF) | Denormalized (star/snowflake) |
| Storage | Row-oriented | Column-oriented |
| Latency | Milliseconds | Seconds to minutes |
| Users | Application servers, customers | Analysts, BI tools |
| Operations | INSERT, UPDATE, DELETE (point) | SELECT with GROUP BY, JOIN (scan) |
| Indexing | B-tree for point lookups | Columnar stats for predicate pushdown |
| Examples | PostgreSQL, MySQL, Oracle | Snowflake, Redshift, BigQuery |
package com.bank.core;
public class OLTPvsOLAP {
public static void main(String[] args) {
System.out.println("OLTP: UPDATE accounts SET balance = "
+ "balance - 50000 WHERE id = 'SAV2001'");
System.out.println(" -> 1 row, 2ms, runs 10000x/sec");
System.out.println();
System.out.println("OLAP: SELECT branch, SUM(amount) "
+ "FROM fact_transactions GROUP BY branch");
System.out.println(" -> 50M rows, 8 sec, runs 10x/day");
}
}
OLTP: UPDATE accounts SET balance = balance - 50000 WHERE id = 'SAV2001'
-> 1 row, 2ms, runs 10000x/sec
OLAP: SELECT branch, SUM(amount) FROM fact_transactions GROUP BY branch
-> 50M rows, 8 sec, runs 10x/day
Why must you NOT run analytics on the production database?
A giant analytical scan consumes CPU, memory, and I/O, can hold locks or saturate the buffer cache, and starves the small transactions. Rajesh's withdrawal that normally takes five milliseconds suddenly takes seconds or times out. The storage model is also wrong: a row store forced to aggregate one column across millions of rows reads every column of every row.
package com.bank.core;
public class ResourceContention {
public static void main(String[] args) {
// Simulating what happens when OLAP runs on OLTP
System.out.println("Normal OLTP latency: 2 ms");
System.out.println("During analytics scan: 3500 ms");
System.out.println();
System.out.println("Root causes:");
System.out.println(" 1. CPU saturated by scan");
System.out.println(" 2. Buffer cache evicted by scan");
System.out.println(" 3. Locks held by long query");
System.out.println(" 4. Row-store reads ALL columns"
+ " to aggregate ONE column");
System.out.println();
System.out.println("Result: Rajesh's payment times out.");
}
}
Normal OLTP latency: 2 ms
During analytics scan: 3500 ms
Root causes:
1. CPU saturated by scan
2. Buffer cache evicted by scan
3. Locks held by long query
4. Row-store reads ALL columns to aggregate ONE column
Result: Rajesh's payment times out.
How do you separate OLTP from OLAP?
The solution is to move data from OLTP into OLAP through ETL, ELT, or change-data-capture (CDC) into a warehouse or lake. This isolates the workloads so analytics scales independently and never degrades customer-facing latency.
# CDC from production PostgreSQL to OLAP warehouse
# Using Debezium to capture every committed change
# Source: OLTP (PostgreSQL) -> Kafka -> OLAP (Redshift)
# Step 1: Debezium captures changes
# Step 2: Kafka streams changes to consumer
# Step 3: Consumer writes to Redshift
# Result: OLAP is seconds behind OLTP
# Analytics runs on Redshift, not production
OLTP (PostgreSQL)
│
│ Debezium CDC
▼
Kafka (change events)
│
│ Consumer
▼
OLAP (Redshift)
│
│ Analytics queries run here
▼
BI Dashboards
What is a star schema?
A star schema is the standard OLAP modelling approach. A central fact table stores events (transactions), and dimension tables store lookup attributes (branch, account, date). The fact table has foreign keys to each dimension. The "star" shape comes from the fact table in the center with dimension tables radiating outward.
-- Fact table: one row per transaction event
CREATE TABLE fact_transactions (
txn_id VARCHAR PRIMARY KEY,
account_id VARCHAR REFERENCES dim_account(account_id),
branch_id INT REFERENCES dim_branch(branch_id),
date_id INT REFERENCES dim_date(date_id),
amount DECIMAL(15,2),
txn_type VARCHAR
);
-- Dimension table: branch attributes
CREATE TABLE dim_branch (
branch_id INT PRIMARY KEY,
branch_name VARCHAR,
city VARCHAR,
region VARCHAR
);
What about HTAP systems?
HTAP (Hybrid Transactional/Analytical Processing) systems attempt to serve both workloads on one engine. Examples include TiDB, SingleStore, and CockroachDB with columnar replicas. However, in a bank the safest conventional pattern is still clear separation so that a fraud analyst's quarterly report can never slow down a customer's payment.
package com.bank.core;
public class HTAPConsideration {
public static void main(String[] args) {
System.out.println("HTAP: one engine for both OLTP + OLAP");
System.out.println("Examples: TiDB, SingleStore");
System.out.println();
System.out.println("Bank preference: clear separation");
System.out.println(" Reason: analyst's report must NEVER");
System.out.println(" slow down a customer's payment.");
System.out.println(" Risk tolerance: zero.");
}
}
HTAP: one engine for both OLTP + OLAP
Examples: TiDB, SingleStore
Bank preference: clear separation
Reason: analyst's report must NEVER
slow down a customer's payment.
Risk tolerance: zero.
What are common interview follow-up questions?
- What is a snowflake schema and how does it differ from a star schema?
- How does change-data-capture work under the hood?
- What are the trade-offs of read replicas vs a separate warehouse?
- How do you handle near-real-time analytics with acceptable lag?
- Why is column-oriented storage better for aggregations?
Visual Overview
OLTP vs OLAP ──────────── OLTP (Row-Oriented) OLAP (Column-Oriented) ┌──────────────────┐ ┌──────────────────┐ │ row1: id|amt|dt │ │ id: 1,2,3,4,5.. │ │ row2: id|amt|dt │ │ amt: 100,200,... │ │ row3: id|amt|dt │ │ dt: Oct,Oct,... │ │ row4: id|amt|dt │ │ │ │ (all cols together)│ │ (each col stored │ │ │ │ separately) │ └──────────────────┘ └──────────────────┘ Fast point read/write Fast column scan/aggregate
Separation Pattern ────────────────── ┌──────────┐ CDC/ETL ┌───────────┐ │ OLTP │─────────▶│ OLAP │ │ (Postgres)│ │(Redshift) │ │ │ │ │ │ Rajesh's │ │ Total per │ │ payment │ │ branch │ │ (2 ms) │ │ (8 sec) │ └──────────┘ └───────────┘ Customer-facing Analyst-facing Never degraded Scales independently
Key Takeaway
OLTP and OLAP are two system types tuned for opposite workloads. OLTP handles many small, fast, concurrent transactions like placing orders or processing payments. It uses normalized schemas so each fact lives in one place, row-oriented storage because you touch whole single rows, indexes for fast point lookups, and ACID transactions for correctness. OLAP handles a smaller number of very heavy queries over large volumes of historical data. It uses denormalized star or snowflake schemas, column-oriented storage because you aggregate a few columns across billions of rows, and it is tuned for large scans rather than point writes.
The reason you must not run heavy analytics on the production OLTP database is resource contention plus a design mismatch. A giant analytical scan consumes CPU, memory, and I/O and can hold locks or saturate the cache, which starves the small transactions, so a withdrawal that normally takes a few milliseconds suddenly takes seconds or times out. The storage model is also wrong, because a row store forced to aggregate one column across millions of rows must read every column of every row.
The fix is to separate them by moving data from OLTP into an OLAP warehouse or lake through an ETL or ELT pipeline or a change-data-capture stream, which isolates the workloads so analytics scales independently and never degrades customer-facing latency. For near-real-time needs you can use read replicas or streaming so the analytics copy is only seconds behind, and HTAP systems try to blend both, but in a bank the safest conventional pattern is clear separation.
In a banking context at the National Bank of India, Rajesh's and Priya's payments were fast single-row writes on the production OLTP database, a CDC sync copied committed transactions into the analytics warehouse, and heavy reports like total spend per branch ran entirely on OLAP. That way an analyst's quarterly report could never slow down a customer's payment.
Remember one sentence: OLTP handles fast point transactions, OLAP handles heavy analytical scans, and you separate them so reports never freeze live operations.
---