Under the Hood: Vectorized OLAP Engines vs. Distributed LSM Tables
Engineers often confuse Wide-Column stores (Apache Cassandra, ScyllaDB, Google Cloud Bigtable) with true Columnar databases (ClickHouse, Snowflake, DuckDB, AWS Redshift, Apache Parquet). Despite both referencing 'columns', their underlying storage engines serve diametrically opposed workloads:
- Wide-Column (Cassandra / ScyllaDB): An OLTP engine designed for massive horizontal distributed writes. Under the hood, data is organized around a
Partition Keyand aClustering Key. Rows are stored in an LSM-tree sorted by clustering key. It is effectively a two-dimensional key-value store:Map<PartitionKey, SortedMap<ClusteringKey, Columns>>. Within a single SSTable a row's columns are stored together, but one logical row can be spread across several SSTables (and the memtable) until compaction merges them. - Columnar (ClickHouse / Parquet): An OLAP engine designed for aggregate analytical queries across billions of rows (e.g.,
SELECT avg(latency), sum(bytes) FROM logs WHERE status = 500). On disk, values for a single column across millions of rows are packed sequentially into compressed data blocks.
Disk Layout: Row-Oriented vs. Pure Columnar
Why Columnar Storage Wins for Analytics: Vectorization & Compression
When calculating an average across 100 million logs, a row-oriented database must read all row data (including user agents, payloads, request URLs) from disk into RAM, discarding 95% of the bytes read. A columnar engine only reads the latency column file from disk.
Furthermore, because identical data types sit adjacent on disk, columnar engines often achieve around 10:1 compression (highly workload-dependent) using specialized codecs:
- Run-Length Encoding (RLE): Sequences of identical values (e.g.,
[200, 200, 200, 200]) compress to[200, count=4]. - Delta Encoding: Timestamps (
1600000000, 1600000001, 1600000003) store only the small deltas (+1, +2), which compress down to single bytes. - SIMD Vectorization: Modern CPUs can execute mathematical operations on 512-bit registers (AVX-512) processing 16 32-bit integers per instruction (actual per-cycle throughput depends on the microarchitecture).