Skip to content

Commit

Permalink
feat: add seek support to join iterator for better performance
Browse files Browse the repository at this point in the history
  • Loading branch information
garethgeorge committed May 5, 2024
1 parent 65d4a1d commit 802146a
Showing 1 changed file with 45 additions and 5 deletions.
50 changes: 45 additions & 5 deletions internal/oplog/indexutil/indexutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,19 @@ type IndexIterator interface {
Next() (int64, bool)
}

type SeekableIndexIterator interface {
IndexIterator
Seek(int64) (int64, bool) // seek to the first recordId >= id and return it or return false.
}

type IndexSearchIterator struct {
c *bolt.Cursor
k []byte
prefix []byte
}

var _ SeekableIndexIterator = &IndexSearchIterator{}

func newSearchIterator(b *bolt.Bucket, prefix []byte) IndexIterator {
c := b.Cursor()
k, _ := c.Seek(prefix)
Expand All @@ -59,13 +66,38 @@ func (i *IndexSearchIterator) Next() (int64, bool) {
return id, true
}

func (i *IndexSearchIterator) Seek(id int64) (int64, bool) {
seekTo := []byte{}
seekTo = append(seekTo, i.prefix...)
seekTo = append(seekTo, serializationutil.Itob(id)...)
k, _ := i.c.Seek(seekTo)
if k == nil || !bytes.HasPrefix(k, i.prefix) {
return 0, false
}
id, err := serializationutil.Btoi(k[len(i.prefix):])
if err != nil {
return 0, false
}
return id, true
}

type JoinIterator struct {
iters []IndexIterator
iters []IndexIterator
seekables []SeekableIndexIterator
}

func NewJoinIterator(iters ...IndexIterator) *JoinIterator {
seekables := make([]SeekableIndexIterator, 0, len(iters))
for _, iter := range iters {
if seekable, ok := iter.(SeekableIndexIterator); ok {
seekables = append(seekables, seekable)
} else {
seekables = append(seekables, nil)
}
}
return &JoinIterator{
iters: iters,
iters: iters,
seekables: seekables,
}
}

Expand Down Expand Up @@ -104,9 +136,17 @@ func (j *JoinIterator) Next() (int64, bool) {
if id == nexts[maxIdx] {
continue
}
nexts[idx], ok = j.iters[idx].Next()
if !ok {
return 0, false

if j.seekables[idx] != nil {
nexts[idx], ok = j.seekables[idx].Seek(nexts[maxIdx])
if !ok {
return 0, false
}
} else {
nexts[idx], ok = j.iters[idx].Next()
if !ok {
return 0, false
}
}
}
}
Expand Down

0 comments on commit 802146a

Please sign in to comment.