build-an-lsm-storage-engine / lesson-17.md
Lesson 17 · SSTables on disk

Ranged SSTable scans

The memtable can scan a key range; an SSTable must too, so range queries work over on-disk data. Today you use the index to seek an SSTable iterator to a start key, giving the same bounded scan across files.

The goal

Start an SSTable iterator at the first key >= a given start key.

Start here - the target
TO DO
Scenario: Seeking an SSTable iterator to a range start
Givenan SSTable with keys "apple", "banana", "cherry", "date", "fig"
Whenan iterator is opened seeking to start = "cherry"
Thenthe first key it yields is "cherry", then "date", then "fig"
Andseeking to start = "coconut" (absent) yields the first key greater than it: "date"
Background

Range scans across the store will merge the memtable’s cursor with one cursor per SSTable, all positioned at the same start key. So an SSTable iterator needs the same seek the memtable got in lesson 4: jump to the first key at or after start and walk forward from there.

The index makes the seek cheap - binary-search it for the first key >= start and set the cursor to that record’s offset. Note the “absent start” case: seeking to a key that isn’t present lands on the next key after it, never skipping data. Now both kinds of source - in-memory and on-disk - present an identical seekable, sorted cursor, which is the last thing the merge iterator needs before it can read across all of them at once.

Make it work
// binary-search the index for the first key >= start, then set
// the iterator's cursor to that record's offset. From there Next()
// walks forward exactly like the full-file iterator.
func (s *SSTable) ScanFrom(start string) Iterator { /* ... */ }
CheckpointDONE
An SSTable iterator can seek to any start key, matching the memtable's scan. Commit and stop here.