lib/storage: speed up search for data block for the given tsids

Use binary search instead of linear scan for looking up the needed
data block inside index block.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3425
This commit is contained in:
Aliaksandr Valialkin 2022-12-03 20:57:19 -08:00
parent c1cd4a9101
commit 05c65bd83f
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1

View file

@ -228,24 +228,29 @@ func (ps *partSearch) readIndexBlock(mr *metaindexRow) (*indexBlock, error) {
} }
func (ps *partSearch) searchBHS() bool { func (ps *partSearch) searchBHS() bool {
for i := range ps.bhs { bhs := ps.bhs
bh := &ps.bhs[i] for len(bhs) > 0 {
// Skip block headers with tsids smaller than the given tsid.
nextTSID: tsid := &ps.BlockRef.bh.TSID
if bh.TSID.Less(&ps.BlockRef.bh.TSID) { n := sort.Search(len(bhs), func(i int) bool {
// Skip blocks with small tsid values. return !bhs[i].TSID.Less(tsid)
continue })
if n == len(bhs) {
// Nothing found.
break
} }
bhs = bhs[n:]
// Invariant: ps.BlockRef.bh.TSID <= bh.TSID // Invariant: tsid <= bh.TSID
if bh.TSID.MetricID != ps.BlockRef.bh.TSID.MetricID { bh := &bhs[0]
// ps.BlockRef.bh.TSID < bh.TSID: no more blocks with the given tsid. if bh.TSID.MetricID != tsid.MetricID {
// tsid < bh.TSID: no more blocks with the given tsid.
// Proceed to the next (bigger) tsid. // Proceed to the next (bigger) tsid.
if !ps.nextTSID() { if !ps.nextTSID() {
return false return false
} }
goto nextTSID continue
} }
// Found the block with the given tsid. Verify timestamp range. // Found the block with the given tsid. Verify timestamp range.
@ -254,6 +259,7 @@ func (ps *partSearch) searchBHS() bool {
// So use linear search instead of binary search. // So use linear search instead of binary search.
if bh.MaxTimestamp < ps.tr.MinTimestamp { if bh.MaxTimestamp < ps.tr.MinTimestamp {
// Skip the block with too small timestamps. // Skip the block with too small timestamps.
bhs = bhs[1:]
continue continue
} }
if bh.MinTimestamp > ps.tr.MaxTimestamp { if bh.MinTimestamp > ps.tr.MaxTimestamp {
@ -269,10 +275,9 @@ func (ps *partSearch) searchBHS() bool {
// Read it. // Read it.
ps.BlockRef.init(ps.p, bh) ps.BlockRef.init(ps.p, bh)
ps.bhs = ps.bhs[i+1:] ps.bhs = bhs[1:]
return true return true
} }
ps.bhs = nil ps.bhs = nil
return false return false
} }