Back to Data Engineering Fundamentals
Q9Question 9 of 10

Difference between OLTP and OLAP (and why not run analytics on production)

Key Concepts
  • OLTP handles many small, fast, concurrent transactions with normalized schemas and row-oriented storage.
  • OLAP handles complex analytical queries over large historical data with star schemas and column-oriented storage.
  • OLTP uses indexes for fast point lookups; OLAP uses columnar scans for aggregations.
  • Running heavy analytics on the production DB starves latency-sensitive transactions of CPU, memory, and I/O.
  • A row-store forced to aggregate one column across millions of rows reads every column of every row, which is slow.
  • Separate them via ETL, ELT, or change-data-capture into a warehouse or lake.
  • Read replicas or streaming keep the analytics copy seconds behind for near-real-time needs.

Definition

OLTP is the fast transactional counter; OLAP is the heavy analytics back office, and you keep them separate so reports never freeze live operations.
  • 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.

SQL
-- 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
JAVA
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);
        }
    }
}
TEXT
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.

SQL
-- 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;
TEXT
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 |

JAVA
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");
    }
}
TEXT
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.

JAVA
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.");
    }
}
TEXT
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.

PYTHON
# 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
DIAGRAM
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.

SQL
-- 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.

JAVA
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.");
    }
}
TEXT
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

DIAGRAM
  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
DIAGRAM
  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.

---

Share
Use ← → arrow keys to navigate