Basic Prerequisites: none beyond basic SQL and Python. This is the on-ramp for readers with no database or systems background.
1. Intuition & Practical Objective
Imagine a library where every book is a one-page record: timestamp, ticker, price, size. One trading day adds 500 million of these records. A relational database stores them the way a librarian shelves books by the order they arrived - and answers “what was the average size today?” by walking every shelf and reading every page, three-quarters of which it does not need.
That is the whole problem in one sentence. A row store (PostgreSQL, MySQL) keeps each record’s fields together, because its job is transactions: “find this one order and update it.” A column store (kdb+, ClickHouse, Parquet, DuckDB) keeps each field together across all records, because a quant’s job is analytics: “sum this one field over a billion rows.”
Three “aha”s, in order:
- The question is always about a few columns, never all of them. A scan for
SUM(size)needs 4 bytes per row, not 24. Storage layout decides whether the disk delivers 4 or 24 bytes - a constant factor decided at write time that no index or query planner can undo. - Scale is the forcing function. At rows, row stores are fine. At rows and thousands of research queries per day, the traffic penalty compounds into hours of wasted wall-clock per study.
- Time is special. Tick data arrives ordered by time, is queried by time windows, and - crucially - must only ever be read as it was known at the time. Row stores offer no vocabulary for that; columnar, time-partitioned stores make it a schema decision.
The practical objective. Understand why the physical layout is a first-class research decision: it sets the storage bill, the query latency, and whether point-in-time correctness is even representable.
2. Mathematical Ground Truth & Derivations
The traffic identity. Let be the number of rows and the record width. A single-field scan touches
so the penalty of a row layout for a -column query is exactly the record-to-payload ratio
For an -byte record and a 4-byte size column, this is .
Cache-line arithmetic (the real mechanism). Memory moves in 64-byte lines. Scanning one 8-byte field:
The row store moves of every line to answer a question about of its bytes - the hardware fetches what you laid out, not what you asked for.
The storage bill. At messages and :
3. Computational Implementation - seeing the 3x with numpy
This is the most convincing demonstration for a beginner: build the same million ticks in an interleaved array (row-like) and a contiguous column, scan one field, and measure. Both the analytic line counts and the measured bandwidth penalty appear.
The analytic ratio is exactly : the interleaved layout drags of every cache line across the bus for a query that needs of its bytes. Both scans return the identical column sum - the difference is purely how much memory the hardware had to fetch. Timing the two scans on the author’s machine (numpy, 20 repetitions) gave ms strided vs ms contiguous - a wall-clock gap that tracks the line-count ratio. Neither the time nor the traffic can be recovered by a smarter query, because the penalty was paid at write time.
4. Failure Modes & First-Principles Breakdowns
- “Just add an index.” Indexes accelerate point lookups; they do nothing for a full-field scan, which is the quant’s dominant query. The penalty is in the bytes fetched per line, not the search.
- “Normalise it like any OLTP schema.” A tidy -table tick schema multiplies joins on a billion-row fact table; the honest design is one wide, time-sorted, columnar fact table plus small reference tables.
- “Compression is a config flag.” Columnar compression works because one column is homogeneous - sorted timestamps delta-compress, repeated symbols dictionary-compress. Row stores cannot exploit either (see 03 · Compression).
- “Storage is cheap, so layout does not matter.” The bill is not storage alone: GB/day and TB/year of unindexed history is re-scanned per query. Layout decides research cadence, not just disk cost.
5. References
- Borror, Jeffry - Q for Mortals (4th ed.), Kx Systems
- Needham & Simons - DuckDB in Action (Manning), ch. 1–2
- Bryant & O’Hallaron - Computer Systems: A Programmer’s Perspective, ch. 6
- Hasbrouck, Joel - Empirical Market Microstructure, ch. 2
6. Connected Graph Bridges
- Index hub: Tick-Level Databases & Time-Series
- Continue: 02 · Storage Formats
- Memory model: Memory & Cache · High-Performance C++ for Trading
- Where the ticks come from: FIX Protocol & Exchange Connectivity
- What consumes them: Event-Driven Backtesting Engines