Iteration And Range Scans

ZoneTree stores keys in order. Iterators expose that order for full scans, range scans, prefix layouts, and reverse reads.

Forward Iteration

using var iterator = zoneTree.CreateIterator();

while (iterator.Next())
{
    Console.WriteLine($"{iterator.CurrentKey}: {iterator.CurrentValue}");
}

Seek

UseSeekto move near a key and continue from there. A forward iterator seeks to the first key greater than or equal to the target key.

using var iterator = zoneTree.CreateIterator();

iterator.Seek(100);

while (iterator.Next())
{
    if (iterator.CurrentKey >= 200)
        break;

    Console.WriteLine(iterator.CurrentValue);
}

Reverse Iteration

using var iterator = zoneTree.CreateReverseIterator();

iterator.Seek(1000);

while (iterator.Next())
{
    Console.WriteLine($"{iterator.CurrentKey}: {iterator.CurrentValue}");
}

Reverse iteration is useful for latest-first time-series queries, descending indexes, and scanning high-key ranges. A reverse iterator seeks to the last key smaller than or equal to the target key.

Iterator Types

ZoneTree iterators can operate with different refresh behavior.

TypeBehavior
IteratorType.AutoRefreshDefault. Scans all available segments and refreshes when the mutable segment moves forward. New writes may appear if their position has not already been passed.
IteratorType.NoRefreshScans all available segments captured by the iterator and does not automatically include newly moved segments. It can be manually refreshed.
IteratorType.SnapshotMoves the mutable segment forward when the iterator is created, then scans read-only, disk, and bottom segments. It does not see later writes.
IteratorType.ReadOnlyRegionLike snapshot, but does not move the mutable segment forward. Manually move the mutable segment first if you need current in-memory writes included.

Use the default iterator for ordinary scans. UseSnapshotwhen you need a stable view and can accept the cost of moving the mutable segment forward.

using var iterator = zoneTree.CreateIterator(IteratorType.Snapshot);

Deleted Records

By default, iterators return live records. PassincludeDeletedRecords: truewhen you need low-level inspection, diagnostics, or custom compaction workflows.

using var iterator = zoneTree.CreateIterator(
    IteratorType.NoRefresh,
    includeDeletedRecords: true);

Normal application scans should usually leave deleted records hidden.

Block Cache Contribution

Disk segment iterator reads do not contribute to the block cache by default. Enable cache contribution when the scan represents a useful working set that is likely to be read again.

using var iterator = zoneTree.CreateIterator(
    IteratorType.AutoRefresh,
    includeDeletedRecords: false,
    contributeToTheBlockCache: true);

For one-off full scans, keep cache contribution disabled so the scan does not evict hotter random-read data.

Low-Level Segment Iterators

The implementation also exposes low-level in-memory and read-only-segment iterators. These are useful for diagnostics and internal tooling, not normal application reads.

Dispose Iterators

Iterators can hold references to active segments. Dispose them when you are done.

using var iterator = zoneTree.CreateIterator();

Long-lived iterators can delay segment disposal, so keep them scoped to the scan.