Newest wins — and the reads get slower — the memtable-first read path across SSTables
A get walks the memtable first, then every SSTable from newest to oldest, returning the first hit it finds — which is correct, but means every flush makes reads slower because there is one more file to consult.
Disk now holds one or more sorted SSTables — but a single get has to know which one to read. The rule is simple, but its cost grows with every flush.
Scene 04
Newest wins — and the reads get slower
- Watch
- Try it
- Predict
- Capture
Three SSTables on the shelf. Two GETs run: one whose key is in the newest file, one whose key is only in the oldest. Watch the cursor descend; watch the counter climb.
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(): # sorted by recencyif key not in sst.key_range: continuev = sst.read(key) # block index + 1 blockif v is FOUND:return v # may be an absence markerreturn not_found # missed every file
# invariant the flush + WAL pipeline maintains:# sst[i].max_seqno < sst[j].max_seqno for newer j# so:# if a key has a live record in sst[i] AND sst[j] (j newer),# the cursor sees sst[j]'s record first and returns IT.# older shadowed records are correct to ignore.# they are NOT correct to delete — see scene 9.
Where this sits in Build an LSM-tree storage engine (LevelDB / RocksDB style)
Scene 04 of 11, in the Read side act — Newest wins; bloom filters skip the misses.. A get walks memtable → SSTables newest-first; first hit wins. Cost grows linearly with file count, especially for misses.
Up next. Reading every file on every miss is unsustainable. We need a way to say 'definitely not here' without paying a disk read — and we need it to be cheap enough to keep on every file.
All 11 scenes in Build an LSM-tree storage engine (LevelDB / RocksDB style) · Every curriculum