Skip to content

Commit 3227bce

Browse files
craig[bot]andy-kimball
andcommitted
Merge #144677
144677: vecindex: improve concurrency test and fix bugs it found r=drewkimball a=andy-kimball #### cspann: fix searcher bugs Fix a couple of bugs in the tree searcher code found by the concurrency test: - When the tree has more than 5 levels, we were resizing the searcher levels slice, but without copying the root level to the resized slice. This caused an unexpected error during search. - The searcher logic was sometimes exiting too early, before it had considered all available parent results. This was causing deletions to sometimes miss finding vectors in the tree. Epic: CRDB-42943 Release note: None #### cspann: fix race condition in vector delete code. The deletion code had a race where it would sometimes attempt to delete a vector from a partition that disallowed deletes. The fix is to convert the Delete and SearchForDelete code paths to use the same retry pattern as Insert and SearchForInsert do. The searchForInsertHelper method has been generalized into a searchForUpdateHelper method that handles both insert and delete cases. Epic: CRDB-42943 Release note: None #### cspann: update TestIndexConcurrency test to delete vectors This commit modifies the TestIndexConcurrency test to delete one vector in each inserted batch. The test interleaves concurrent inserts, deletes, searches, and splits on multiple goroutines in order to find concurrency bugs. The modification found multiple issues that are fixed in subsequent commits. Epic: CRDB-42943 Release note: None #### vecindex: improve vecindex concurrency test Increase the coverage of the vecindex concurrency test by adding foreground querying while the load is happening in the background. Also add deletes during the load (though disabled due to a bug it found). Increase the number of iterations and the insert block size. Use a small partition size and build beam size to increase the frequency of splits. Fix an efficiency issue the test found: when searching for a deletion vector, set the MatchKey field in the searcher so that we don't bother buffering up vectors which can never match. Epic: CRDB-42943 Release note: None #### vecindex: suppress partition not found error in SearchPartitions The SearchPartitions method is spec'd to return InvalidLevel for any partition that is not found in the tree. However, the vecstore was instead returning ErrPartitionNotFound, which was causing occasional insertion failures under stress. This commit updates the vecstore to suppress ErrPartitionNotFound, mapping it to a PartitionToSearch value of InvalidLevel, MissingState and Count=0. Epic: CRDB-42943 Release note: None Co-authored-by: Andrew Kimball <[email protected]>
2 parents 40124c1 + a0593d7 commit 3227bce

File tree

10 files changed

+345
-239
lines changed

10 files changed

+345
-239
lines changed

pkg/sql/vecindex/cspann/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ go_library(
3434
"//pkg/sql/vecindex/cspann/quantize",
3535
"//pkg/sql/vecindex/cspann/utils",
3636
"//pkg/sql/vecindex/cspann/workspace",
37+
"//pkg/util/buildutil",
3738
"//pkg/util/container/heap",
3839
"//pkg/util/log",
3940
"//pkg/util/num32",

pkg/sql/vecindex/cspann/commontest/storetests.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,14 @@ func (suite *StoreTestSuite) TestSearchPartitions() {
346346
treeKey := store.MakeTreeKey(suite.T(), treeID)
347347

348348
// Create non-root partition with some vectors in it.
349-
testPartitionKey, _ := suite.createTestPartition(store, treeKey)
349+
testPartitionKey, testPartition := suite.createTestPartition(store, treeKey)
350350

351351
// Create another partition.
352352
testPartitionKey2 := cspann.PartitionKey(20)
353353
metadata := cspann.PartitionMetadata{
354354
Level: cspann.SecondLevel,
355355
Centroid: vector.T{2, 4},
356-
StateDetails: cspann.MakeReadyDetails(),
356+
StateDetails: cspann.MakeSplittingDetails(10, 20),
357357
}
358358
suite.NoError(store.TryCreateEmptyPartition(suite.ctx, treeKey, testPartitionKey2, metadata))
359359
vectors := vector.MakeSet(2)
@@ -368,20 +368,36 @@ func (suite *StoreTestSuite) TestSearchPartitions() {
368368

369369
suite.NoError(store.RunTransaction(suite.ctx, func(txn cspann.Txn) error {
370370
searchSet := cspann.SearchSet{MaxResults: 2}
371-
toSearch := []cspann.PartitionToSearch{{Key: testPartitionKey}, {Key: testPartitionKey2}}
371+
toSearch := []cspann.PartitionToSearch{
372+
{Key: testPartitionKey},
373+
{Key: cspann.PartitionKey(99)}, // Partition does not exist.
374+
{Key: testPartitionKey2},
375+
}
372376
err := txn.SearchPartitions(suite.ctx, treeKey, toSearch, vector.T{6, 1}, &searchSet)
373377
suite.NoError(err)
378+
379+
// Validate partition info.
380+
suite.Equal(cspann.SecondLevel, toSearch[0].Level)
381+
suite.Equal(testPartition.Metadata().StateDetails, toSearch[0].StateDetails)
382+
suite.Equal(3, toSearch[0].Count)
383+
384+
suite.Equal(cspann.InvalidLevel, toSearch[1].Level)
385+
suite.Equal(cspann.PartitionStateDetails{}, toSearch[1].StateDetails)
386+
suite.Equal(0, toSearch[1].Count)
387+
388+
suite.Equal(cspann.SecondLevel, toSearch[2].Level)
389+
suite.Equal(metadata.StateDetails, toSearch[2].StateDetails)
390+
suite.Equal(2, toSearch[2].Count)
391+
392+
// Validate search results.
374393
result1 := cspann.SearchResult{
375394
QuerySquaredDistance: 4.2, ErrorBound: 50.99, CentroidDistance: 7.21,
376395
ParentPartitionKey: testPartitionKey2, ChildKey: partitionKey4, ValueBytes: valueBytes4}
377396
result2 := cspann.SearchResult{
378397
QuerySquaredDistance: 8, ErrorBound: 0, CentroidDistance: 0,
379398
ParentPartitionKey: testPartitionKey, ChildKey: partitionKey3, ValueBytes: valueBytes3}
380399
suite.Equal(cspann.SearchResults{result1, result2}, RoundResults(searchSet.PopResults(), 2))
381-
suite.Equal(cspann.SecondLevel, toSearch[0].Level)
382-
suite.Equal(3, toSearch[0].Count)
383-
suite.Equal(cspann.SecondLevel, toSearch[1].Level)
384-
suite.Equal(2, toSearch[1].Count)
400+
385401
return nil
386402
}))
387403
}

0 commit comments

Comments
 (0)