Cassandra Bloom Filters

A Bloom filter is a space-efficient data structure that answers one question very quickly: "Is this partition key definitely NOT in this SSTable?" If the answer is yes, Cassandra skips the SSTable entirely — saving a disk read. If the answer is maybe, Cassandra checks the SSTable. Bloom filters are stored in memory and make Cassandra's read path dramatically faster on tables with many SSTables.

The "Guest List" Analogy

Imagine a nightclub bouncer with a rough list of guest names. The list might say "John Smith is NOT on the list" with certainty, but if it says "John Smith might be on the list," the bouncer still checks the actual guest book to confirm. A Bloom filter works exactly like that rough list — it gives definite NO answers quickly and probabilistic YES answers that still require verification.

SSTable Bloom Filter:

Query: "Is partition key 'order-uuid-X' in SSTable-4?"
  → Bloom filter says: "Definitely NOT here"
  → Skip SSTable-4 entirely ✓ (zero disk I/O)

Query: "Is partition key 'order-uuid-Y' in SSTable-4?"
  → Bloom filter says: "Maybe here"
  → Check SSTable-4's partition index → found (true positive) ✓
                                       OR not found (false positive) ⚠

How a Bloom Filter Works

A Bloom filter is a bit array of N bits, all initialized to zero. When you add a key, you hash it with multiple hash functions and set the corresponding bits to 1. To check if a key is present, you hash it the same way and check whether all those bits are 1. If any bit is 0, the key is definitely absent. If all bits are 1, the key is probably present (but could be a false positive).

Bit array (10 bits): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Add key "order-A" (3 hash functions → positions 2, 5, 8):
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0]

Add key "order-B" (hash → positions 1, 4, 7):
[0, 1, 1, 0, 1, 1, 0, 1, 1, 0]

Check "order-A": positions 2, 5, 8 → all 1 → MAYBE ✓
Check "order-Z": positions 0, 3, 6 → bits are 0 → DEFINITELY NOT ✓
Check "order-Q": positions 1, 4, 8 → all 1 → MAYBE (false positive ⚠)

False Positives in Bloom Filters

A false positive occurs when the Bloom filter says "maybe" for a key that is not actually in the SSTable. Cassandra then reads the SSTable's partition index — an unnecessary disk read. False positives waste I/O but never produce incorrect data. The false positive rate is configurable.

False Positive Rate (FPR) trade-off:

Low FPR (e.g., 0.01 = 1%):   Very accurate → fewer disk reads
                               Larger Bloom filter → more memory

High FPR (e.g., 0.10 = 10%): More false positives → more disk reads
                               Smaller Bloom filter → less memory

Configuring the Bloom Filter False Positive Rate

Each table has its own Bloom filter setting. The default false positive chance is 0.1 (10%). Reduce it for read-heavy tables to decrease unnecessary disk reads at the cost of more memory.

-- More accurate Bloom filter (1% false positive rate):
CREATE TABLE hot_orders (
  order_id UUID PRIMARY KEY,
  total    DECIMAL
) WITH bloom_filter_fp_chance = 0.01;

-- Less accurate but smaller (15% false positive rate):
CREATE TABLE cold_archive (
  record_id UUID PRIMARY KEY,
  data      TEXT
) WITH bloom_filter_fp_chance = 0.15;

-- Alter existing table:
ALTER TABLE hot_orders WITH bloom_filter_fp_chance = 0.01;

Bloom Filter Memory Usage

Bloom filter memory scales with the number of partition keys in the SSTable and the configured false positive rate. More partitions or a lower FPR means a larger filter.

Approximate Bloom filter size formula:
  size ≈ (-n × ln(p)) / (ln(2)²)

Where:
  n = number of partition keys in the SSTable
  p = desired false positive rate

Examples (n = 1,000,000 partitions):
  FPR 0.10 (10%): ~600 KB
  FPR 0.01 (1%):  ~1.2 MB
  FPR 0.001 (0.1%): ~1.8 MB

Bloom Filter Storage

Each SSTable has its own Bloom filter stored in a Filter.db file alongside the SSTable. When Cassandra starts, it loads all Bloom filters into memory (off-heap). Bloom filters from newly created SSTables are built during the flush process.

SSTable files:
  mb-1-big-Data.db        ← row data
  mb-1-big-Filter.db      ← Bloom filter (loaded into off-heap RAM)
  mb-1-big-Index.db       ← partition index
  ...

Checking Bloom Filter Effectiveness

nodetool gives you metrics on Bloom filter hit and false positive rates per table, helping you decide whether to lower the false positive chance.

nodetool tablestats ecommerce

Table: orders_by_customer
  Bloom filter false positives:      234
  Bloom filter false ratio:          0.0023
  Bloom filter space used:           1.2 MB
  Bloom filter off-heap memory used: 1.2 MB

A false ratio above 0.01 (1%) on a read-heavy table is a signal to lower bloom_filter_fp_chance.

Compaction and Bloom Filters

When compaction merges SSTables, it builds a new Bloom filter for the merged SSTable automatically. The old Bloom filters (from the merged SSTables) are discarded from memory. This keeps the in-memory Bloom filter footprint proportional to the current SSTable count rather than accumulating over time.

When to Tune Bloom Filters

Scenario                             Recommendation
──────────────────────────────────────────────────────────────
Read-heavy table with many SSTables  Lower FPR to 0.01 or 0.001
Write-heavy table, rarely read       Keep default 0.1 to save memory
Time-series data (TWCS compaction)   Default usually fine; few SSTables
Large archive table, cold reads OK   Higher FPR (0.2) to save memory
Memory constrained cluster           Raise FPR cluster-wide carefully

Summary

Bloom filters are in-memory probabilistic structures that allow Cassandra to skip SSTables that definitely do not contain a requested partition key, saving disk I/O. They produce no false negatives but may produce false positives, causing an occasional unnecessary SSTable check. The bloom_filter_fp_chance table property controls the trade-off between memory usage and read efficiency. Lower the false positive rate on read-intensive tables to improve query performance, and monitor false ratios with nodetool to know when tuning is needed.

Leave a Comment

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