From f755e5e681489df58725ad8939565344d69e323e Mon Sep 17 00:00:00 2001 From: yangxuan Date: Thu, 26 Mar 2026 19:57:16 +0800 Subject: [PATCH] fix: filter deleted indexes in GetIndexedSegments to prevent stale segment loading GetIndexedSegments included deleted index entries in targetIndices but skipped them in the counting loop, causing indexedFields to never equal len(targetIndices) when deleted entries existed. This made every segment appear unindexed after drop+create index cycles, forcing GetQueryVChanPositions to fall back to loading stale pre-compaction segments instead of the optimized one. See also: #48557 Signed-off-by: yangxuan --- internal/datacoord/index_meta.go | 6 +----- internal/datacoord/index_meta_test.go | 29 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/internal/datacoord/index_meta.go b/internal/datacoord/index_meta.go index 4f75c3799a39f..cfc2a746c7be9 100644 --- a/internal/datacoord/index_meta.go +++ b/internal/datacoord/index_meta.go @@ -638,7 +638,7 @@ func (m *indexMeta) GetIndexedSegments(collectionID int64, segmentIDs, fieldIDs matchedFields := typeutil.NewUniqueSet() targetIndices := lo.Filter(lo.Values(fieldIndexes), func(index *model.Index, _ int) bool { - return fieldIDSet.Contain(index.FieldID) + return fieldIDSet.Contain(index.FieldID) && !index.IsDeleted }) for _, index := range targetIndices { matchedFields.Insert(index.FieldID) @@ -652,10 +652,6 @@ func (m *indexMeta) GetIndexedSegments(collectionID int64, segmentIDs, fieldIDs checkSegmentState := func(indexes *typeutil.ConcurrentMap[UniqueID, *model.SegmentIndex]) bool { indexedFields := 0 for _, index := range targetIndices { - if !fieldIDSet.Contain(index.FieldID) || index.IsDeleted { - continue - } - if segIdx, ok := indexes.Get(index.IndexID); ok && segIdx.IndexState == commonpb.IndexState_Finished { indexedFields += 1 } diff --git a/internal/datacoord/index_meta_test.go b/internal/datacoord/index_meta_test.go index ec578bf5455c8..0ee074ede2c29 100644 --- a/internal/datacoord/index_meta_test.go +++ b/internal/datacoord/index_meta_test.go @@ -817,6 +817,35 @@ func TestMeta_GetIndexedSegment(t *testing.T) { segments := m.GetIndexedSegments(collID+1, []int64{segID}, []int64{fieldID}) assert.Len(t, segments, 0) }) + + t.Run("with deleted index entries", func(t *testing.T) { + // Simulate drop+create index cycles: add deleted index entries for the same field. + // Previously, deleted entries inflated len(targetIndices), causing the indexed check + // to always fail (indexedFields=1 != len(targetIndices)=N). + deletedIndexID1 := indexID + 100 + deletedIndexID2 := indexID + 200 + m.indexes[collID][deletedIndexID1] = &model.Index{ + CollectionID: collID, + FieldID: fieldID, + IndexID: deletedIndexID1, + IndexName: "old_idx_1", + IsDeleted: true, + } + m.indexes[collID][deletedIndexID2] = &model.Index{ + CollectionID: collID, + FieldID: fieldID, + IndexID: deletedIndexID2, + IndexName: "old_idx_2", + IsDeleted: true, + } + + segments := m.GetIndexedSegments(collID, []int64{segID}, []int64{fieldID}) + assert.Len(t, segments, 1, "segment should be indexed even with deleted index entries") + + // Cleanup + delete(m.indexes[collID], deletedIndexID1) + delete(m.indexes[collID], deletedIndexID2) + }) } func TestMeta_MarkIndexAsDeleted(t *testing.T) {