Why an operational database struggles with analytical work
standardintermediateThe database serving your application is tuned for a workload that looks nothing like analytics. Application queries touch a few rows by key, return quickly, and run constantly; analytical queries scan millions of rows, read a handful of columns from each, and run for seconds or minutes. The mismatch is structural rather than a matter of tuning. A row-oriented store keeps all of a row's columns together, which is ideal when you want a whole row and wasteful when you want two columns from fifty million rows, because the engine reads every column to get the two it needs. Indexes help point lookups and stop helping once a query touches a large fraction of the table, at which point a full scan is the plan. And the resources those scans consume — memory, disk bandwidth, buffer cache — are the same resources every application query depends on, so a single large report can evict the working set that keeps ordinary queries fast, and the effect outlasts the report. None of this means the operational database is bad at analytics in principle; it means it is optimised for the opposite access pattern, and the two workloads compete for one set of resources. Small analytical queries over recent data are usually fine there. Large scans over history are what want a separate system, and the next concept is about how the data gets there.
Think of it as
A shop's till versus its accounts department. The till is built to serve one customer very quickly, over and over. The accounts department reads every transaction of the quarter and produces one number. Asking the cashier to also total the quarter, at the counter, while customers wait, is not a criticism of the cashier — it is asking one thing to do two jobs whose demands conflict.
- Operational (row-oriented, indexed)
- Seek to one row by key
- Read that row's columns together — exactly what row storage gives you
- Working set stays in the buffer cache
- Predictable, millisecond latency
- Analytical on the same store
- Scan a large fraction of the table
- Read all columns to use two — most of the bytes are discarded
- Evicts the working set, so ordinary queries slow down afterwards
- Competes for the same memory and disk bandwidth as live traffic
Two workloads, one database
Remember: Operational and analytical queries have opposite access patterns — a few rows with all their columns, versus many rows with a few of their columns — and a row-oriented, index-tuned store is built for the first. Large scans read every column to use two, stop benefiting from indexes once they cover most of a table, and evict the buffer cache that keeps live traffic fast, with an effect that outlasts the query. That is resource competition between two workloads, not a defect, and it is why large historical analysis wants a separate system.
See also: event collection pipelines and pre aggregation · oltp workload characteristics · keeping reporting off the transactional database · polyglot persistence · read replicas and consistency

