Overview
A log-structured merge tree trades read work for write speed. Instead of modifying pages in place, it turns all writes into sequential appends and sorts the data later. It underlies Cassandra, RocksDB, LevelDB, HBase and many others.
How it works
Writes land in a log and a memtable, flush to level files, and compaction merges them downward.
write -> WAL (disk) + memtable (RAM, sorted)
memtable full -> flush -> L0 SSTable
compaction: L0 + L1 -> merged sorted L1 ... Ln
read -> memtable -> L0 files -> L1 ... (bloom filter skips files)
Size-tiered compaction favors write throughput and uses more space. Leveled compaction keeps one sorted run per level, which lowers read and space amplification at the price of more write amplification.
Three amplification factors describe the trade-off. Write amplification is how many times a byte is rewritten by compaction, read amplification is how many files a lookup may consult, and space amplification is how much extra disk obsolete versions occupy. Tuning one pushes the others. For example, adding more bloom filter bits lowers read cost for a little memory, while a larger memtable produces fewer, bigger flushes. Measure on production-like data, because synthetic uniform keys hide the skew that makes real compactions expensive.
Pitfalls
- Ignoring write amplification: each byte may be rewritten many times across levels, which wears SSDs.
- Deleting heavily without planning for tombstone cleanup, so scans slow down.
- Running disks near full, leaving compaction no room to work.
- Choosing a compaction strategy without measuring the real read to write ratio.
Key takeaways
- LSM trees convert random writes into sequential ones.
- Compaction is the hidden cost; monitor its backlog.
- Bloom filters and indexes keep reads tolerable.
- Pick the engine by workload shape, not popularity.