Definitely-not-here, in one bitmap — Bloom filters on every SSTable
Each SSTable carries a tiny bitmap that, for any key, answers 'definitely not in this file' or 'maybe' — so missing-key reads skip almost every file without touching disk, making the newest-first walk tolerable even with many files.
Walking every file on every miss is the cliff. The way out is a tiny per-file structure that says 'definitely not here' before we touch disk — and is small enough to keep in RAM for every file.
Scene 05
Definitely-not-here, in one bitmap
- Watch
- Try it
- Predict
- Capture
Five SSTables, each topped with a bloom bitmap. Watch a missing-key GET (most files reply 'definitely no') and a present-key GET (one file replies 'hit'). Disk reads counter shows how many files we ACTUALLY had to read.
Highlighted lines are the ones running in the diagram right now.
def get(key):if key in memtable: return memtable[key]for sst in sstables_newest_first():if not sst.bloom.maybe_contains(key):continue # skip — no disk readv = sst.read(key) # 'maybe' → block readif v is FOUND: return v # may be tombstonereturn not_found
# bloom filter: per-file bitmap of m bits set by k hash functions# false-positive rate ≈ (1 - e^(-kn/m))^k# practical:# 1.5 bits/key → ~50% FP (almost useless)# 10 bits/key → ~1% FP (canonical default)# 15.5 bits/key → ~0.1% FP (diminishing returns)# RAM grows linearly with bits/key. Pick 10 unless …
Where this sits in Build an LSM-tree storage engine (LevelDB / RocksDB style)
Scene 05 of 11, in the Read side act — Newest wins; bloom filters skip the misses.. Each SSTable carries a bloom filter that says 'definitely no' or 'maybe' — eliminating disk reads on misses, not on hits.
Up next. Bloom filters bound the cost of looking; they don't bound the number of files. Flushes keep adding files and disk grows. Sooner or later we have to merge them — that's the GC of the LSM world.
All 11 scenes in Build an LSM-tree storage engine (LevelDB / RocksDB style) · Every curriculum