Skip to content

Commit 669e425

Browse files
committed
Use SeekPrefixGE to avoid unnecessary disk read in Get function
1 parent 8638640 commit 669e425

File tree

3 files changed

+31
-6
lines changed

3 files changed

+31
-6
lines changed

db.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ func (d *DB) getInternal(key []byte, b *Batch, s *Snapshot) ([]byte, io.Closer,
560560
logger: d.opts.Logger,
561561
cmp: d.cmp,
562562
equal: d.equal,
563+
split: d.split,
563564
newIters: d.newIters,
564565
snapshot: seqNum,
565566
key: key,

get_iter.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type getIter struct {
2121
logger Logger
2222
cmp Compare
2323
equal Equal
24+
split Split
2425
newIters tableNewIters
2526
snapshot uint64
2627
key []byte
@@ -159,13 +160,20 @@ func (g *getIter) Next() (*InternalKey, base.LazyValue) {
159160
files := g.l0[n-1].Iter()
160161
g.l0 = g.l0[:n-1]
161162
iterOpts := IterOptions{logger: g.logger, snapshotForHideObsoletePoints: g.snapshot}
162-
g.levelIter.init(context.Background(), iterOpts, g.cmp, nil /* split */, g.newIters,
163+
g.levelIter.init(context.Background(), iterOpts, g.cmp, g.split, g.newIters,
163164
files, manifest.L0Sublevel(n), internalIterOpts{})
164165
g.levelIter.initRangeDel(&g.rangeDelIter)
165166
bc := levelIterBoundaryContext{}
166167
g.levelIter.initBoundaryContext(&bc)
167168
g.iter = &g.levelIter
168-
g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone)
169+
170+
// Compute the key prefix for bloom filtering if split function is
171+
// specified, or use the user key as default.
172+
prefix := g.key
173+
if g.split != nil {
174+
prefix = g.key[:g.split(g.key)]
175+
}
176+
g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone)
169177
if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey {
170178
g.iterKey = nil
171179
g.iterValue = base.LazyValue{}
@@ -184,14 +192,21 @@ func (g *getIter) Next() (*InternalKey, base.LazyValue) {
184192
}
185193

186194
iterOpts := IterOptions{logger: g.logger, snapshotForHideObsoletePoints: g.snapshot}
187-
g.levelIter.init(context.Background(), iterOpts, g.cmp, nil /* split */, g.newIters,
195+
g.levelIter.init(context.Background(), iterOpts, g.cmp, g.split, g.newIters,
188196
g.version.Levels[g.level].Iter(), manifest.Level(g.level), internalIterOpts{})
189197
g.levelIter.initRangeDel(&g.rangeDelIter)
190198
bc := levelIterBoundaryContext{}
191199
g.levelIter.initBoundaryContext(&bc)
192200
g.level++
193201
g.iter = &g.levelIter
194-
g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone)
202+
203+
// Compute the key prefix for bloom filtering if split function is
204+
// specified, or use the user key as default.
205+
prefix := g.key
206+
if g.split != nil {
207+
prefix = g.key[:g.split(g.key)]
208+
}
209+
g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone)
195210
if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey {
196211
g.iterKey = nil
197212
g.iterValue = base.LazyValue{}

level_iter.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -797,15 +797,24 @@ func (l *levelIter) SeekPrefixGE(
797797
}
798798
return l.verify(l.largestBoundary, base.LazyValue{})
799799
}
800-
// It is possible that we are here because bloom filter matching failed. In
800+
// It is possible that we are here because bloom filter matching failed. In
801801
// that case it is likely that all keys matching the prefix are wholly
802802
// within the current file and cannot be in the subsequent file. In that
803803
// case we don't want to go to the next file, since loading and seeking in
804804
// there has some cost. Additionally, for sparse key spaces, loading the
805805
// next file will defeat the optimization for the next SeekPrefixGE that is
806806
// called with flags.TrySeekUsingNext(), since for sparse key spaces it is
807807
// likely that the next key will also be contained in the current file.
808-
if n := l.split(l.iterFile.LargestPointKey.UserKey); l.cmp(prefix, l.iterFile.LargestPointKey.UserKey[:n]) < 0 {
808+
var n int
809+
if l.split != nil {
810+
// If the split function is specified, calculate the prefix length accordingly.
811+
n = l.split(l.iterFile.LargestPointKey.UserKey)
812+
} else {
813+
// If the split function is not specified, the entire key is used as the
814+
// prefix. This case can occur when getIter uses SeekPrefixGE.
815+
n = len(l.iterFile.LargestPointKey.UserKey)
816+
}
817+
if l.cmp(prefix, l.iterFile.LargestPointKey.UserKey[:n]) < 0 {
809818
return nil, base.LazyValue{}
810819
}
811820
return l.verify(l.skipEmptyFileForward())

0 commit comments

Comments
 (0)