Levels — a staircase that bounds reads — non-overlapping key ranges, 10x per tier
Sort the SSTables into numbered tiers where each tier (except the freshly-flushed top) holds non-overlapping key ranges that are 10x bigger than the tier above — and a get touches at most one file per tier, capping read cost regardless of total data.
Compaction merges files. But picking WHICH files — and how the survivors are arranged on disk — is the choice that defines an LSM's personality.
Scene 07
Levels — a staircase that bounds reads
- Watch
- Try it
- Predict
- Capture
Watch the staircase build out: L0 overlapping, then L1 non-overlapping across the keyspace, then L2. A get for k descends one file per level — not 100+.
Highlighted lines are the ones running in the diagram right now.
# L0 — overlapping allowed (it inherits memtable arrival order)# L1+ — non-overlapping within a level:# for any two files f, g in level L (L >= 1):# f.key_range ∩ g.key_range = ∅# bytes(L_i) ≈ multiplier × bytes(L_{i-1})# default multiplier = 10 (LevelDB / RocksDB)# implication: a get touches# memtable + #L0 (bloom-checked) + 1 per (L1..Ln)
def compact_leveled(i):f = pick_file(L[i])overlap = [g for g in L[i+1] if g.key_range ∩ f.key_range]new_files = merge_sort_split(f, overlap, target_size=L[i+1].size)atomic_swap_files(remove=[f] + overlap,add_to_level={i+1: new_files},)# invariant preserved: L[i+1] still non-overlapping.
Where this sits in Build an LSM-tree storage engine (LevelDB / RocksDB style)
Scene 07 of 11, in the Compaction act — Levels, write amplification, the amp triangle.. L0 may overlap; L1+ enforce non-overlap per level; each level is ~10× the size of the one above. A get touches at most one file per tier.
Up next. Bounded levels are not free. Every byte gets rewritten on its way down — and the multiplier we just chose is the cost dial. Time to count the bytes that hit the disk.
All 11 scenes in Build an LSM-tree storage engine (LevelDB / RocksDB style) · Every curriculum