Skip to content

Commit 426de06

Browse files
committed
cspann: move level searcher init code to Init method
Previously, the searcher initialized the search set for each level in the Next method. This commit moves that code into the levelSearcher.Init method. This makes some planned refactoring easier in an another commit. Epic: CRDB-42943 Release note: None
1 parent a226eb5 commit 426de06

File tree

2 files changed

+60
-52
lines changed

2 files changed

+60
-52
lines changed

pkg/sql/vecindex/cspann/search_set.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ type SearchSet struct {
203203
tempResult SearchResult
204204
}
205205

206+
// Init sets up the search set for use. While it's not necessary to call this
207+
// when the search set has been newly allocated (i.e. with zero'd memory), this
208+
// method is useful for re-initializing it after previous usage has left it in
209+
// an undefined state.
210+
func (ss *SearchSet) Init() {
211+
ss.deDuper.Clear()
212+
*ss = SearchSet{
213+
deDuper: ss.deDuper,
214+
candidates: ss.candidates[:0],
215+
}
216+
}
217+
206218
// Count returns the number of search candidates in the set.
207219
// NOTE: This can be greater than MaxResults + MaxExtraResults in the case where
208220
// pruning has not yet taken place.

pkg/sql/vecindex/cspann/searcher.go

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,7 @@ func (s *searcher) Init(idx *Index, idxCtx *Context, searchSet *SearchSet) {
7373
func (s *searcher) Next(ctx context.Context) (ok bool, err error) {
7474
if len(s.levels) == 0 {
7575
root := &s.levelStorage[0]
76-
root.Init(s.idx, s.idxCtx, nil /* parent */, &s.searchSet.Stats)
77-
78-
// Return enough search results to ensure that:
79-
// 1. The number of results requested by the caller is respected.
80-
// 2. There are enough samples for calculating stats.
81-
// 3. There are enough results for adaptive querying to dynamically expand
82-
// the beam size (up to 2x the base beam size).
83-
root.SearchSet().MaxResults = max(
84-
s.searchSet.MaxResults, s.idx.options.QualitySamples, s.idxCtx.options.BaseBeamSize*2)
85-
root.SearchSet().MaxExtraResults = s.searchSet.MaxExtraResults
76+
root.Init(s.idx, s.idxCtx, nil /* parent */, s.searchSet)
8677

8778
// Search the root patition in order to discover its level.
8879
err = root.SearchRoot(ctx)
@@ -110,39 +101,7 @@ func (s *searcher) Next(ctx context.Context) (ok bool, err error) {
110101
s.levels = utils.EnsureSliceLen(s.levels, n)
111102
s.levels[0] = *root
112103
for i := 1; i < n; i++ {
113-
var maxResults, maxExtraResults int
114-
var matchKey KeyBytes
115-
if i == n-1 {
116-
// This is the last level to be searched, so ensure that:
117-
// 1. The number of results requested by the caller is respected.
118-
// 2. There are enough samples for re-ranking to work well, even if
119-
// there are deleted vectors.
120-
// 3. There are enough samples for calculating stats.
121-
maxResults = s.searchSet.MaxResults
122-
maxExtraResults = s.searchSet.MaxExtraResults
123-
if !s.idxCtx.options.SkipRerank {
124-
maxResults, maxExtraResults = IncreaseRerankResults(maxResults)
125-
if s.searchSet.MaxExtraResults > maxExtraResults {
126-
maxExtraResults = s.searchSet.MaxExtraResults
127-
}
128-
}
129-
if s.idxCtx.level != LeafLevel && s.idxCtx.options.UpdateStats {
130-
maxResults = max(maxResults, s.idx.options.QualitySamples)
131-
}
132-
matchKey = s.searchSet.MatchKey
133-
} else {
134-
// This is an interior level, so ensure that:
135-
// 1. There are enough samples for calculating stats.
136-
// 2. There are enough results for adaptive querying to dynamically
137-
// expand the beam size (up to 2x the base beam size).
138-
maxResults = max(s.idx.options.QualitySamples, s.idxCtx.options.BaseBeamSize*2)
139-
}
140-
141-
s.levels[i].Init(s.idx, s.idxCtx, &s.levels[i-1], &s.searchSet.Stats)
142-
searchSet := s.levels[i].SearchSet()
143-
searchSet.MaxResults = maxResults
144-
searchSet.MaxExtraResults = maxExtraResults
145-
searchSet.MatchKey = matchKey
104+
s.levels[i].Init(s.idx, s.idxCtx, &s.levels[i-1], s.searchSet)
146105
}
147106
}
148107

@@ -234,23 +193,60 @@ type levelSearcher struct {
234193
// Init sets up the level searcher for iteration. It reuses memory where
235194
// possible.
236195
func (s *levelSearcher) Init(
237-
idx *Index, idxCtx *Context, parent *levelSearcher, stats *SearchStats,
196+
idx *Index, idxCtx *Context, parent *levelSearcher, searchSet *SearchSet,
238197
) {
239198
*s = levelSearcher{
240-
idx: idx,
241-
idxCtx: idxCtx,
242-
parent: parent,
243-
stats: stats,
244-
searchSet: s.searchSet, // Preserve existing searchSet memory.
199+
idx: idx,
200+
idxCtx: idxCtx,
201+
parent: parent,
202+
stats: &searchSet.Stats,
245203
}
246-
if parent != nil {
204+
205+
s.searchSet.Init()
206+
if parent == nil {
207+
// This is the root, so its level is not yet known. Return enough search
208+
// results to ensure that:
209+
// 1. The number of results requested by the caller is respected.
210+
// 2. There are enough samples for calculating stats.
211+
// 3. There are enough results for adaptive querying to dynamically expand
212+
// the beam size (up to 2x the base beam size).
213+
s.searchSet.MaxResults = max(
214+
s.searchSet.MaxResults, idx.options.QualitySamples, idxCtx.options.BaseBeamSize*2)
215+
s.searchSet.MaxExtraResults = searchSet.MaxExtraResults
216+
} else {
247217
if parent.Level() == InvalidLevel {
248218
panic(errors.AssertionFailedf("parent level cannot be InvalidLevel"))
249219
}
250220
s.level = parent.Level() - 1
221+
if s.level > idxCtx.level {
222+
// This is an interior level, so ensure that:
223+
// 1. There are enough samples for calculating stats.
224+
// 2. There are enough results for adaptive querying to dynamically
225+
// expand the beam size (up to 2x the base beam size).
226+
s.searchSet.MaxResults =
227+
max(idx.options.QualitySamples, idxCtx.options.BaseBeamSize*2)
228+
} else {
229+
// This is the last level to be searched, so ensure that:
230+
// 1. The number of results requested by the caller is respected.
231+
// 2. There are enough samples for re-ranking to work well, even if
232+
// there are deleted vectors.
233+
// 3. There are enough samples for calculating stats.
234+
maxResults := searchSet.MaxResults
235+
maxExtraResults := searchSet.MaxExtraResults
236+
if !idxCtx.options.SkipRerank {
237+
maxResults, maxExtraResults = IncreaseRerankResults(maxResults)
238+
if searchSet.MaxExtraResults > maxExtraResults {
239+
maxExtraResults = searchSet.MaxExtraResults
240+
}
241+
}
242+
if idxCtx.level != LeafLevel && idxCtx.options.UpdateStats {
243+
maxResults = max(maxResults, idx.options.QualitySamples)
244+
}
245+
s.searchSet.MaxResults = maxResults
246+
s.searchSet.MaxExtraResults = maxExtraResults
247+
s.searchSet.MatchKey = searchSet.MatchKey
248+
}
251249
}
252-
253-
s.searchSet.Clear()
254250
}
255251

256252
// SearchSet returns the target search set to which results are copied for each

0 commit comments

Comments
 (0)