Skip to content

Commit

Permalink
db: avoid loading later files for a level in SeekPrefixGE
Browse files Browse the repository at this point in the history
Don't load arbitrarily later files during levelIter.SeekPrefixGE. This avoids
unnecessary IO and CPU overhead.

Close cockroachdb#3575.
  • Loading branch information
jbowens committed May 15, 2024
1 parent 5e941d8 commit d4498e4
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 26 deletions.
12 changes: 12 additions & 0 deletions level_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,18 @@ func (l *levelIter) loadFile(file *fileMetadata, dir int) loadFileReturnIndicato
file = l.files.Prev()
continue
}
// If we're in prefix iteration, it's possible this file's smallest
// boundary is large enough to prove the file cannot possibly contain
// any keys within the iteration prefix. Loading the next file is
// unnecessary. This has been observed in practice on slow shared
// storage. See #3575.
if l.prefix != nil && l.cmp(file.SmallestPointKey.UserKey[:l.split(file.SmallestPointKey.UserKey)], l.prefix) > 0 {
// Note that because we don't update l.iter, a subsequent call to
// SeekPrefixGE with TrySeekUsingNext()=true will load the file
// (returning newFileLoaded) and disable TrySeekUsingNext before
// performing a seek in the file.
return noFileLoaded
}

iterKinds := iterPointKeys
if l.rangeDelIterPtr != nil {
Expand Down
20 changes: 20 additions & 0 deletions testdata/iter_histories/prefix_iteration
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,23 @@ seek-prefix-ge c@10
----
b@0: (b@0, .)
c@3: (c@3, .)

# Test a seek for a prefix that falls entirely in the gap between file
# boundaries. The iterator stats should indicate that no blocks are loaded.

define bloom-bits-per-key=100
L4
b@0.SET.10:b@0
L4
d@3.SET.10:d@3
----
L4:
000004:[b@0#10,SET-b@0#10,SET]
000005:[d@3#10,SET-d@3#10,SET]

combined-iter
seek-prefix-ge c@10
stats
----
.
stats: seeked 1 times (1 internal); stepped 0 times (0 internal)
14 changes: 7 additions & 7 deletions testdata/iterator_seek_opt
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ seek-prefix-ge d
d: (2, .)
stats: seeked 22 times (21 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 8
SeekPrefixGEs with trySeekUsingNext: 6
SeekPrefixGEs with trySeekUsingNext: 5

# Shifting bounds, with non-overlapping and monotonic bounds, but using
# SetOptions. A set-options sits between every two seeks. We don't call
Expand All @@ -260,7 +260,7 @@ seek-ge b
b: (1, .)
stats: seeked 23 times (22 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 8
SeekPrefixGEs with trySeekUsingNext: 6
SeekPrefixGEs with trySeekUsingNext: 5

iter
set-options lower=c upper=e
Expand All @@ -270,7 +270,7 @@ seek-ge c
c: (1, .)
stats: seeked 24 times (23 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 8
SeekPrefixGEs with trySeekUsingNext: 6
SeekPrefixGEs with trySeekUsingNext: 5

# NB: Equal bounds.

Expand All @@ -282,7 +282,7 @@ seek-ge d
d: (2, .)
stats: seeked 25 times (24 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 10
SeekPrefixGEs with trySeekUsingNext: 6
SeekPrefixGEs with trySeekUsingNext: 5

iter
set-options lower=a upper=c
Expand All @@ -292,7 +292,7 @@ seek-prefix-ge b
b: (1, .)
stats: seeked 26 times (25 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 10
SeekPrefixGEs with trySeekUsingNext: 6
SeekPrefixGEs with trySeekUsingNext: 5

iter
set-options lower=c upper=e
Expand All @@ -302,7 +302,7 @@ seek-prefix-ge c
c: (1, .)
stats: seeked 27 times (26 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 10
SeekPrefixGEs with trySeekUsingNext: 6
SeekPrefixGEs with trySeekUsingNext: 5

# NB: Equal bounds.

Expand All @@ -314,4 +314,4 @@ seek-prefix-ge d
d: (2, .)
stats: seeked 28 times (27 internal); stepped 2 times (1 fwd/1 rev, internal: 1 fwd/3 rev)
SeekGEs with trySeekUsingNext: 10
SeekPrefixGEs with trySeekUsingNext: 8
SeekPrefixGEs with trySeekUsingNext: 6
18 changes: 1 addition & 17 deletions testdata/level_iter
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,8 @@ b#2,SET:2
iter
seek-prefix-ge d
next
next
----
d#4,SET:4
dd#5,SET:5
.

iter
Expand All @@ -180,27 +178,19 @@ dd#5,SET:5
iter
seek-prefix-ge d
next
prev
prev
----
d#4,SET:4
dd#5,SET:5
d#4,SET:4
c#3,SET:3
.

iter
seek-prefix-ge d
prev
----
d#4,SET:4
c#3,SET:3

iter
seek-prefix-ge dd
prev
----
dd#5,SET:5
d#4,SET:4

iter lower=a
seek-ge a
Expand Down Expand Up @@ -449,10 +439,8 @@ d#4,SET:4
iter upper=e
seek-prefix-ge d
next
next
----
d#4,SET:4
dd#5,SET:5
.

iter lower=dd
Expand All @@ -464,17 +452,13 @@ dd#5,SET:5

iter lower=d
seek-prefix-ge dd
prev
----
dd#5,SET:5
d#4,SET:4

iter lower=c
seek-prefix-ge dd
prev
----
dd#5,SET:5
d#4,SET:4

iter lower=c
seek-lt c
Expand Down
3 changes: 1 addition & 2 deletions testdata/merging_iter
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,7 @@ err=injected error
# L2.000029.Close() = nil <err="injected error">
err=injected error
# L1.000028.SeekPrefixGE("b") = (c#27,SET,"27")
# L2.000029.SeekPrefixGE("b") = nil <err="injected error">
err=injected error
.

# Inject errors during L1.{Next,NextPrefix,Prev}.

Expand Down

0 comments on commit d4498e4

Please sign in to comment.