Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
db: enhance Iterator with limited iteration mode
Limited iteration mode is a best-effort way for the caller to specify an exclusive forward or inclusive reverse limit on each limited-iteration call. The limit lasts only for the duration of the call. The limit is exclusive for forward iteration and inclusive for reverse iteration. Iterator supports WithLimit variants for SeekGE, SeekLT, Next, Prev. These are motivated by the O(N^2) complexity we observe when doing coordinated iteration over the lock table and MVCC keys in CockroachDB where all the intents in the lock table are deleted but have not yet been compacted away. The O(N^2) complexity arises in two cases: - Limited scans: the extreme is a limited scan with a limit of 1. Each successive scan traverses N, N-1, ... locks. - Mix of forward/reverse iteration in a single scan: A Next/SeekGE will incur a cost of N and the Prev/SeekLT another cost of N. This situation could be potentially fixed with a narrower solution, given the constrained way that the combination of forward and backward iteration is used in CockroachDB code, but it would be fragile. The limited iteration mode solves it in a more general way. The implementation of limited iteration eschews best-effort behavior (though that would reduce some comparisons) so that it can be deterministic and be tested via the metamorphic test. The existing seek optimizations are impacted in the following way: - Use next before seeking: - Repeated seeks (forward or reverse) with monotonic bounds: this optimization operates at mergingIter and below and is therefore unaffected by whatever Iterator may be doing with the keys exposed by mergingIter. - monotonic SeekPrefixGE: SeekPrefixGE does not expose a limited iteration variant since the prefix comparison performed by Iterator already ensures the absence of quadratic behavior. - Noop seeks (forward and reverse): this optimization happens purely in Iterator. It is altered to account for limited iteration, and forks into 2 paths, (a) truly a noop, (b) the limit on the preceding seek has positioned the iterator at a key that is outside the limit. In case (b) the underlying mergingIter does not need to be seeked, but there is work to be done in finding an appropriate prev or next entry. See https://github.com/sumeerbhola/cockroach/tree/iter_coord for the corresponding CockroachDB change that uses these methods.
- Loading branch information