Cassandra MemTable and SSTable

MemTables and SSTables are the two storage layers at the heart of Cassandra's write and read paths. MemTables hold recent writes in memory for fast access. SSTables hold persistent data on disk. Together they form a layered storage system called a Log-Structured Merge Tree (LSM tree) that makes Cassandra exceptionally fast for writes.

The Sticky Note and Filing Cabinet Analogy

When you receive new information during a meeting, you first jot it on a sticky note (MemTable — fast, in memory, temporary). When the meeting ends, you file those notes into the proper folders in your cabinet (SSTable — permanent, organized, on disk). You never erase old cabinet entries — you add new ones on top, and periodically clean up the cabinet by merging related folders (compaction).

MemTable

A MemTable is an in-memory, sorted data structure that holds the most recently written rows for a table. Every write goes to the MemTable immediately after the commit log, making writes extremely fast — RAM access is orders of magnitude faster than disk access.

MemTable properties:
  - Lives in JVM heap memory
  - One MemTable per table (active) + optional off-heap MemTables
  - Sorted by partition key, then clustering columns
  - Serves read queries for recent writes before they flush to disk
  - Flushed to SSTable when it reaches the size threshold

MemTable Flush Triggers

Trigger                          Configuration
──────────────────────────────────────────────────────────────
Heap threshold exceeded          memtable_heap_space_in_mb (default: 1/4 heap)
Off-heap threshold exceeded      memtable_offheap_space_in_mb
Commit log size limit            commitlog_total_space_in_mb
Manual flush                     nodetool flush
Clean shutdown                   automatic before exit

Configuring MemTable Allocation Type

# cassandra.yaml — where MemTable memory comes from:
memtable_allocation_type: heap_buffers        # default: JVM heap
# OR
memtable_allocation_type: offheap_buffers     # off-heap (reduces GC pressure)
# OR
memtable_allocation_type: offheap_objects     # fully off-heap rows

Reading from MemTable

When a read query arrives, Cassandra checks the MemTable first alongside SSTables. If a partition was recently written but not yet flushed, the MemTable provides the freshest version. The read path merges MemTable data with SSTable data using timestamps to determine the final result.

SSTable

An SSTable (Sorted String Table) is an immutable file written to disk when a MemTable flushes. Once written, an SSTable never changes. Updates and deletes create new SSTables, not modifications to existing ones. Compaction periodically merges multiple SSTables into one.

SSTable properties:
  - Immutable after creation
  - Sorted by partition key, then clustering columns
  - Compressed by default (LZ4 compression)
  - Contains Bloom filter, partition index, and data
  - Multiple SSTables can exist per table simultaneously

SSTable File Components

File                    Contents
──────────────────────────────────────────────────────────────
Data.db                 Actual row data (columns and values)
Index.db                Partition key → byte offset mapping
Summary.db              Coarse index of the Index.db (in memory)
Filter.db               Bloom filter (probabilistic key lookup)
Statistics.db           Table metadata, histograms, min/max tokens
CompressionInfo.db      Compression chunk offsets
TOC.txt                 List of all SSTable component files
Digest.crc32            Checksum for data integrity verification

Data.db Layout

Data.db structure (simplified):

[Partition Header: key=customer-uuid-A, token=-4.6Q]
  [Row: clustering=2024-01-05, col: total=99.99, status='pending']
  [Row: clustering=2024-02-12, col: total=45.00, status='shipped']
[Partition Header: key=customer-uuid-B, token=-1.2Q]
  [Row: clustering=2024-01-20, col: total=80.00, status='pending']
...

SSTable Compression

Cassandra compresses SSTables in chunks (default 64 KB per chunk). The CompressionInfo.db file maps each compressed chunk's offset so Cassandra can seek directly to any chunk without decompressing the entire file.

ALTER TABLE orders_by_customer
  WITH compression = {
    'class': 'LZ4Compressor',    -- fastest; default since Cassandra 3.0
    'chunk_length_in_kb': 64
  };

-- Other compressor options:
-- 'SnappyCompressor'   -- good balance of speed and ratio
-- 'DeflateCompressor'  -- highest compression ratio, slower
-- 'ZstdCompressor'     -- best ratio with tunable speed (Cassandra 4.0+)
-- 'NoopCompressor'     -- disables compression

SSTable Accumulation Over Time

Each flush creates a new SSTable. Without compaction, the SSTable count grows indefinitely. A read query must check every SSTable for the requested partition — more SSTables means slower reads.

Day 1:  [SST-1]
Day 2:  [SST-1] [SST-2]
Day 3:  [SST-1] [SST-2] [SST-3]
...
Day 30: [SST-1] ... [SST-30]   ← 30 files to check per read

After compaction:
Day 30: [SST-merged]            ← 1 file to check per read

Viewing SSTable Information

# Count SSTables per table:
nodetool tablestats ecommerce | grep "SSTable count"

SSTable count: 8

# List SSTable files on disk:
ls /var/lib/cassandra/data/ecommerce/orders_by_customer-*/

# Inspect SSTable metadata:
sstablemetadata /var/lib/cassandra/data/ecommerce/ \
  orders_by_customer-*/mb-1-big-Data.db

MemTable vs SSTable Quick Reference

Property            MemTable                   SSTable
──────────────────────────────────────────────────────────────
Location            RAM (JVM heap or off-heap) Disk
Mutability          Mutable                    Immutable
Lifetime            Until flush                Until compaction
Write speed         RAM speed (~ns)            Disk speed (~ms)
Read role           Most recent writes         Historical data
Created by          Write operations           MemTable flush
Removed by          Flushing to SSTable        Compaction

Off-Heap MemTables (Cassandra 2.1+)

By default, MemTable data lives in the JVM heap. Large MemTables increase garbage collection pressure, causing GC pauses that affect latency. Off-heap MemTables store row data outside the JVM heap, reducing GC pressure significantly for write-heavy workloads.

memtable_allocation_type: offheap_buffers

Summary

MemTables receive all writes in memory for speed, backed by the commit log for durability. When a MemTable reaches its size limit, it flushes to an immutable SSTable on disk. SSTables accumulate over time and compaction periodically merges them to maintain read performance. Compression reduces SSTable size and I/O cost with minimal CPU overhead. Understanding MemTable and SSTable behavior is essential for tuning Cassandra's memory settings, compression choices, and compaction strategy.

Leave a Comment

Your email address will not be published. Required fields are marked *