From 307d87316155f6602856dfae0ec4752a94f43c2e Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Fri, 15 Sep 2023 12:15:14 +0530 Subject: [PATCH 01/11] Use get batch api badger --- go.mod | 2 +- go.sum | 4 +- posting/list_test.go | 32 ++++++++++++++++ posting/lists.go | 91 +++++++++++++++++++++++++++++++++++--------- worker/task.go | 18 +++++++-- 5 files changed, 122 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 19b2e5ef5be..9fa85c1754e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/IBM/sarama v1.45.1 github.com/Masterminds/semver/v3 v3.3.1 github.com/blevesearch/bleve/v2 v2.5.1 - github.com/dgraph-io/badger/v4 v4.7.0 + github.com/dgraph-io/badger/v4 v4.5.2-0.20250218121059-0faedd88140e github.com/dgraph-io/dgo/v250 v250.0.0-preview4 github.com/dgraph-io/gqlgen v0.13.2 github.com/dgraph-io/gqlparser/v2 v2.2.2 diff --git a/go.sum b/go.sum index 938b0458a7f..458e8590d61 100644 --- a/go.sum +++ b/go.sum @@ -122,8 +122,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger/v4 v4.7.0 h1:Q+J8HApYAY7UMpL8d9owqiB+odzEc0zn/aqOD9jhc6Y= -github.com/dgraph-io/badger/v4 v4.7.0/go.mod h1:He7TzG3YBy3j4f5baj5B7Zl2XyfNe5bl4Udl0aPemVA= +github.com/dgraph-io/badger/v4 v4.5.2-0.20250218121059-0faedd88140e h1:sZmnvDqloFjehWjr6f/G5O8ANbhenwSYdkGxkTR2Bww= +github.com/dgraph-io/badger/v4 v4.5.2-0.20250218121059-0faedd88140e/go.mod h1:aSwx/bXKT3/WRl9rn2BrTU+tfRQlFPKlOsqRTdcpHB8= github.com/dgraph-io/dgo/v250 v250.0.0-preview4 h1:DkS6iFI6RwStXRzQxT5v8b6NLqqHQi0xKSK6FvcEwYo= github.com/dgraph-io/dgo/v250 v250.0.0-preview4/go.mod h1:6nnKW4tYiai9xI6NSCrxaBgUGG1YI/+KlY+Tc7smqXY= github.com/dgraph-io/gqlgen v0.13.2 h1:TNhndk+eHKj5qE7BenKKSYdSIdOGhLqxR1rCiMso9KM= diff --git a/posting/list_test.go b/posting/list_test.go index 356860049de..23c395f0886 100644 --- a/posting/list_test.go +++ b/posting/list_test.go @@ -493,7 +493,10 @@ func TestAddMutation_mrjn1(t *testing.T) { func TestReadSingleValue(t *testing.T) { defer setMaxListSize(maxListSize) maxListSize = math.MaxInt32 +<<<<<<< HEAD require.Equal(t, nil, pstore.DropAll()) +======= +>>>>>>> 6fbd525d2 (Use get batch api badger) // We call pl.Iterate and then stop iterating in the first loop when we are reading // single values. This test confirms that the two functions, getFirst from this file @@ -502,6 +505,7 @@ func TestReadSingleValue(t *testing.T) { key := x.DataKey(x.AttrInRootNamespace("value"), 1240) ol, err := getNew(key, ps, math.MaxUint64) require.NoError(t, err) +<<<<<<< HEAD N := uint64(10000) for i := uint64(2); i <= N; i += 2 { edge := &pb.DirectedEdge{ @@ -514,6 +518,19 @@ func TestReadSingleValue(t *testing.T) { kData := ol.getMutation(i + 1) writer := NewTxnWriter(pstore) if err := writer.SetAt(key, kData, BitDeltaPosting, i+1); err != nil { +======= + N := int(10000) + for i := 2; i <= N; i += 2 { + edge := &pb.DirectedEdge{ + Value: []byte("ho hey there" + strconv.Itoa(i)), + } + txn := Txn{StartTs: uint64(i)} + addMutationHelper(t, ol, edge, Set, &txn) + require.NoError(t, ol.commitMutation(uint64(i), uint64(i)+1)) + kData := ol.getMutation(uint64(i)) + writer := NewTxnWriter(pstore) + if err := writer.SetAt(key, kData, BitDeltaPosting, uint64(i)); err != nil { +>>>>>>> 6fbd525d2 (Use get batch api badger) require.NoError(t, err) } writer.Flush() @@ -523,12 +540,16 @@ func TestReadSingleValue(t *testing.T) { kvs, err := ol.Rollup(nil, txn.StartTs-3) require.NoError(t, err) require.NoError(t, writePostingListToDisk(kvs)) +<<<<<<< HEAD // Delete item from global cache before reading, as we are not updating the cache in the test memoryLayer.del(key) +======= +>>>>>>> 6fbd525d2 (Use get batch api badger) ol, err = getNew(key, ps, math.MaxUint64) require.NoError(t, err) } +<<<<<<< HEAD j := uint64(3) if j < ol.minTs { j = ol.minTs @@ -538,6 +559,17 @@ func TestReadSingleValue(t *testing.T) { k, err := tx.cache.GetSinglePosting(key) require.NoError(t, err) checkValue(t, ol, string(k.Postings[0].Value), j) +======= + j := 2 + if j < int(ol.minTs) { + j = int(ol.minTs) + } + for ; j < i+6; j++ { + tx := NewTxn(uint64(j)) + k, err := tx.cache.GetSinglePosting(key) + require.NoError(t, err) + checkValue(t, ol, string(k.Postings[0].Value), uint64(j)) +>>>>>>> 6fbd525d2 (Use get batch api badger) } } } diff --git a/posting/lists.go b/posting/lists.go index 1def3fdb4da..de5407464f9 100644 --- a/posting/lists.go +++ b/posting/lists.go @@ -330,32 +330,32 @@ func (lc *LocalCache) readPostingListAt(key []byte) (*pb.PostingList, error) { return pl, err } -// GetSinglePosting retrieves the cached version of the first item in the list associated with the -// given key. This is used for retrieving the value of a scalar predicats. -func (lc *LocalCache) GetSinglePosting(key []byte) (*pb.PostingList, error) { - // This would return an error if there is some data in the local cache, but we couldn't read it. - getListFromLocalCache := func() (*pb.PostingList, error) { - lc.RLock() - - pl := &pb.PostingList{} - if delta, ok := lc.deltas[string(key)]; ok && len(delta) > 0 { - err := proto.Unmarshal(delta, pl) - lc.RUnlock() - return pl, err - } +func (lc *LocalCache) GetSinglePostingFromLocalCache(key []byte) (*pb.PostingList, error) { + lc.RLock() - l := lc.plists[string(key)] + pl := &pb.PostingList{} + if delta, ok := lc.deltas[string(key)]; ok && len(delta) > 0 { + err := proto.Unmarshal(delta, pl) lc.RUnlock() + return pl, err + } - if l != nil { - return l.StaticValue(lc.startTs) - } + l := lc.plists[string(key)] + lc.RUnlock() - return nil, nil + if l != nil { + return l.StaticValue(lc.startTs) } + return nil, nil +} + +// GetSinglePosting retrieves the cached version of the first item in the list associated with the +// given key. This is used for retrieving the value of a scalar predicats. +func (lc *LocalCache) GetSinglePosting(key []byte) (*pb.PostingList, error) { + // This would return an error if there is some data in the local cache, but we couldn't read it. getPostings := func() (*pb.PostingList, error) { - pl, err := getListFromLocalCache() + pl, err := lc.GetSinglePostingFromLocalCache(key) // If both pl and err are empty, that means that there was no data in local cache, hence we should // read the data from badger. if pl != nil || err != nil { @@ -388,6 +388,59 @@ func (lc *LocalCache) GetSinglePosting(key []byte) (*pb.PostingList, error) { return pl, nil } +func (lc *LocalCache) GetBatchSinglePosting(keys [][]byte) ([]*pb.PostingList, error) { + results := make([]*pb.PostingList, len(keys)) + remaining_keys := make([][]byte, 0) + for i, key := range keys { + if pl, err := lc.GetSinglePostingFromLocalCache(key); pl != nil && err != nil { + results[i] = pl + } else { + remaining_keys = append(remaining_keys, key) + } + } + + txn := pstore.NewTransactionAt(lc.startTs, false) + items, err := txn.GetBatch(remaining_keys) + if err != nil { + fmt.Println(err, keys) + return nil, err + } + idx := 0 + + for i := 0; i < len(results); i++ { + if results[i] != nil { + continue + } + pl := &pb.PostingList{} + err = items[idx].Value(func(val []byte) error { + if err := proto.Unmarshal(val, pl); err != nil { + return err + } + return nil + }) + idx += 1 + results[i] = pl + } + + for i := 0; i < len(results); i++ { + pl := results[i] + idx := 0 + for _, postings := range pl.Postings { + if hasDeleteAll(postings) { + return nil, nil + } + if postings.Op != Del { + pl.Postings[idx] = postings + idx++ + } + } + pl.Postings = pl.Postings[:idx] + results[i] = pl + } + + return results, err +} + // Get retrieves the cached version of the list associated with the given key. func (lc *LocalCache) Get(key []byte) (*List, error) { return lc.getInternal(key, true) diff --git a/worker/task.go b/worker/task.go index 73ccce87743..c3d19690dc6 100644 --- a/worker/task.go +++ b/worker/task.go @@ -428,6 +428,7 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) er out := &pb.Result{} outputs[start/width] = out + cache := make([]*pb.PostingList, 0) for i := start; i < end; i++ { select { case <-ctx.Done(): @@ -442,9 +443,20 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) er fcs := &pb.FacetsList{FacetsList: make([]*pb.Facets, 0)} // TODO Figure out how it is stored if !getMultiplePosting { - pl, err := qs.cache.GetSinglePosting(key) - if err != nil { - return err + if len(cache) == 0 { + keys := make([][]byte, 10) + keys[0] = key + for j := i + 1; j < i+10 && j < end; j++ { + keys[j-i] = x.DataKey(q.Attr, q.UidList.Uids[j]) + } + cache, err = qs.cache.GetBatchSinglePosting(keys) + if err != nil { + return err + } + } + pl := cache[0] + if len(cache) > 1 { + cache = cache[1:] } if pl == nil || len(pl.Postings) == 0 { out.UidMatrix = append(out.UidMatrix, &pb.List{}) From 15e9149b0cb02a4659c1ec202408408ad3b8e9c2 Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 18 Feb 2025 18:51:45 +0530 Subject: [PATCH 02/11] fxied test --- posting/list_test.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/posting/list_test.go b/posting/list_test.go index 23c395f0886..356860049de 100644 --- a/posting/list_test.go +++ b/posting/list_test.go @@ -493,10 +493,7 @@ func TestAddMutation_mrjn1(t *testing.T) { func TestReadSingleValue(t *testing.T) { defer setMaxListSize(maxListSize) maxListSize = math.MaxInt32 -<<<<<<< HEAD require.Equal(t, nil, pstore.DropAll()) -======= ->>>>>>> 6fbd525d2 (Use get batch api badger) // We call pl.Iterate and then stop iterating in the first loop when we are reading // single values. This test confirms that the two functions, getFirst from this file @@ -505,7 +502,6 @@ func TestReadSingleValue(t *testing.T) { key := x.DataKey(x.AttrInRootNamespace("value"), 1240) ol, err := getNew(key, ps, math.MaxUint64) require.NoError(t, err) -<<<<<<< HEAD N := uint64(10000) for i := uint64(2); i <= N; i += 2 { edge := &pb.DirectedEdge{ @@ -518,19 +514,6 @@ func TestReadSingleValue(t *testing.T) { kData := ol.getMutation(i + 1) writer := NewTxnWriter(pstore) if err := writer.SetAt(key, kData, BitDeltaPosting, i+1); err != nil { -======= - N := int(10000) - for i := 2; i <= N; i += 2 { - edge := &pb.DirectedEdge{ - Value: []byte("ho hey there" + strconv.Itoa(i)), - } - txn := Txn{StartTs: uint64(i)} - addMutationHelper(t, ol, edge, Set, &txn) - require.NoError(t, ol.commitMutation(uint64(i), uint64(i)+1)) - kData := ol.getMutation(uint64(i)) - writer := NewTxnWriter(pstore) - if err := writer.SetAt(key, kData, BitDeltaPosting, uint64(i)); err != nil { ->>>>>>> 6fbd525d2 (Use get batch api badger) require.NoError(t, err) } writer.Flush() @@ -540,16 +523,12 @@ func TestReadSingleValue(t *testing.T) { kvs, err := ol.Rollup(nil, txn.StartTs-3) require.NoError(t, err) require.NoError(t, writePostingListToDisk(kvs)) -<<<<<<< HEAD // Delete item from global cache before reading, as we are not updating the cache in the test memoryLayer.del(key) -======= ->>>>>>> 6fbd525d2 (Use get batch api badger) ol, err = getNew(key, ps, math.MaxUint64) require.NoError(t, err) } -<<<<<<< HEAD j := uint64(3) if j < ol.minTs { j = ol.minTs @@ -559,17 +538,6 @@ func TestReadSingleValue(t *testing.T) { k, err := tx.cache.GetSinglePosting(key) require.NoError(t, err) checkValue(t, ol, string(k.Postings[0].Value), j) -======= - j := 2 - if j < int(ol.minTs) { - j = int(ol.minTs) - } - for ; j < i+6; j++ { - tx := NewTxn(uint64(j)) - k, err := tx.cache.GetSinglePosting(key) - require.NoError(t, err) - checkValue(t, ol, string(k.Postings[0].Value), uint64(j)) ->>>>>>> 6fbd525d2 (Use get batch api badger) } } } From 6070c0fcdb067f934175c606a2bb6db106fca4fb Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 12:39:06 +0530 Subject: [PATCH 03/11] chnaging something --- x/x.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x/x.go b/x/x.go index db2053f0706..6b791e7497e 100644 --- a/x/x.go +++ b/x/x.go @@ -909,10 +909,8 @@ func DivideAndRule(num int) (numGo, width int) { numGo, width = 64, 0 for ; numGo >= 1; numGo /= 2 { widthF := math.Ceil(float64(num) / float64(numGo)) - if numGo == 1 || widthF >= 256.0 { - width = int(widthF) - return - } + width = int(widthF) + return } return } From d48e38fabf44556f88b9e579d855dcc0b175d21e Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 13:00:03 +0530 Subject: [PATCH 04/11] fixed bug --- worker/task.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/worker/task.go b/worker/task.go index c3d19690dc6..5d7d5ea1a1a 100644 --- a/worker/task.go +++ b/worker/task.go @@ -446,10 +446,12 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) er if len(cache) == 0 { keys := make([][]byte, 10) keys[0] = key + lastI := 0 for j := i + 1; j < i+10 && j < end; j++ { keys[j-i] = x.DataKey(q.Attr, q.UidList.Uids[j]) + lastI = j - i } - cache, err = qs.cache.GetBatchSinglePosting(keys) + cache, err = qs.cache.GetBatchSinglePosting(keys[:lastI+1]) if err != nil { return err } From 2d4dd9e622ab7a06bcbacaee99347cabce18df75 Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 14:38:43 +0530 Subject: [PATCH 05/11] added cache stats --- posting/mvcc.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/posting/mvcc.go b/posting/mvcc.go index 5af668d0855..6910fca698b 100644 --- a/posting/mvcc.go +++ b/posting/mvcc.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "encoding/hex" + "fmt" "math" "strconv" "sync" @@ -415,7 +416,7 @@ func initMemoryLayer(cacheSize int64, removeOnUpdate bool) *MemoryLayer { ml.removeOnUpdate = removeOnUpdate ml.statsHolder = NewStatsHolder() if cacheSize > 0 { - cache, err := ristretto.NewCache[[]byte, *CachePL](&ristretto.Config[[]byte, *CachePL]{ + cache, err := ristretto.NewCache(&ristretto.Config[[]byte, *CachePL]{ // Use 5% of cache memory for storing counters. NumCounters: int64(float64(cacheSize) * 0.05 * 2), MaxCost: int64(float64(cacheSize) * 0.95), @@ -436,9 +437,10 @@ func initMemoryLayer(cacheSize int64, removeOnUpdate bool) *MemoryLayer { for range ticker.C { // Record the posting list cache hit ratio ostats.Record(context.Background(), x.PLCacheHitRatio.M(m.Ratio())) + fmt.Println("CACHE STATS: ", ml.cache.numCacheRead.Load(), ml.cache.numCacheReadFails.Load(), ml.cache.numCacheSave.Load()) if EnableDetailedMetrics { - x.NumPostingListCacheSave.M(ml.cache.numCacheRead.Load()) + x.NumPostingListCacheSave.M(ml.cache.numCacheSave.Load()) x.NumPostingListCacheRead.M(ml.cache.numCacheRead.Load()) x.NumPostingListCacheReadFail.M(ml.cache.numCacheReadFails.Load()) } From 93e23338624a5e3b68c89425d947ff2602d4b3a2 Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 15:06:25 +0530 Subject: [PATCH 06/11] added uids cache --- posting/list.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/posting/list.go b/posting/list.go index 6e9a37e8b93..c031b5aa099 100644 --- a/posting/list.go +++ b/posting/list.go @@ -100,6 +100,10 @@ type MutableLayer struct { // We also cache some things required for us to update currentEntries faster currentUids map[uint64]int // Stores the uid to index mapping in the currentEntries posting list + + // Cache for calculated UIDS + isUidsCalculated bool + calculatedUids []uint64 } func newMutableLayer() *MutableLayer { @@ -110,6 +114,8 @@ func newMutableLayer() *MutableLayer { length: math.MaxInt, committedUids: make(map[uint64]*pb.Posting), committedUidsTime: math.MaxUint64, + isUidsCalculated: false, + calculatedUids: []uint64{}, } } @@ -136,6 +142,8 @@ func (mm *MutableLayer) clone() *MutableLayer { length: mm.length, lastEntry: mm.lastEntry, committedUidsTime: mm.committedUidsTime, + isUidsCalculated: mm.isUidsCalculated, + calculatedUids: mm.calculatedUids, } } @@ -1691,6 +1699,36 @@ func (l *List) ApproxLen() int { return l.mutationMap.len() + codec.ApproxLen(l.plist.Pack) } +func (l *List) calculateUids() error { + l.RLock() + if l.mutationMap.isUidsCalculated { + l.RUnlock() + return nil + } + res := make([]uint64, 0, l.ApproxLen()) + + err := l.iterate(l.mutationMap.committedUidsTime, 0, func(p *pb.Posting) error { + if p.PostingType == pb.Posting_REF { + res = append(res, p.Uid) + } + return nil + }) + + l.RUnlock() + + if err != nil { + return err + } + + l.Lock() + defer l.Unlock() + + l.mutationMap.calculatedUids = res + l.mutationMap.isUidsCalculated = true + + return nil +} + // Uids returns the UIDs given some query params. // We have to apply the filtering before applying (offset, count). // WARNING: Calling this function just to get UIDs is expensive @@ -1700,6 +1738,13 @@ func (l *List) Uids(opt ListOptions) (*pb.List, error) { } getUidList := func() (*pb.List, error, bool) { + l.calculateUids() + if l.mutationMap.isUidsCalculated { + l.RLock() + defer l.RUnlock() + out := &pb.List{Uids: l.mutationMap.calculatedUids} + return out, nil, opt.Intersect != nil + } // Pre-assign length to make it faster. l.RLock() defer l.RUnlock() From 196900cdf566ac6875732cf9682dac7d6935782e Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 15:08:04 +0530 Subject: [PATCH 07/11] added changes --- posting/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posting/list.go b/posting/list.go index c031b5aa099..f0595aff105 100644 --- a/posting/list.go +++ b/posting/list.go @@ -1701,7 +1701,7 @@ func (l *List) ApproxLen() int { func (l *List) calculateUids() error { l.RLock() - if l.mutationMap.isUidsCalculated { + if l.mutationMap == nil || l.mutationMap.isUidsCalculated { l.RUnlock() return nil } From 47518b52c5a5d621f5a2f3eac76bb1ce406a06fd Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 15:09:40 +0530 Subject: [PATCH 08/11] added changes --- posting/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posting/list.go b/posting/list.go index f0595aff105..ac234411b7b 100644 --- a/posting/list.go +++ b/posting/list.go @@ -1739,7 +1739,7 @@ func (l *List) Uids(opt ListOptions) (*pb.List, error) { getUidList := func() (*pb.List, error, bool) { l.calculateUids() - if l.mutationMap.isUidsCalculated { + if l.mutationMap != nil && l.mutationMap.isUidsCalculated { l.RLock() defer l.RUnlock() out := &pb.List{Uids: l.mutationMap.calculatedUids} From 84fcef1a4e1d18ffcef85690575d7c4634f59276 Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 15:12:20 +0530 Subject: [PATCH 09/11] added changes --- posting/mvcc.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/posting/mvcc.go b/posting/mvcc.go index 6910fca698b..c2c19c8124f 100644 --- a/posting/mvcc.go +++ b/posting/mvcc.go @@ -607,6 +607,9 @@ func ReadPostingList(key []byte, it *badger.Iterator) (*List, error) { } l.minTs = item.Version() + if l.mutationMap == nil { + l.mutationMap = newMutableLayer() + } // No need to do Next here. The outer loop can take care of skipping // more versions of the same key. return l, nil From 6f2da9846aa27da9c7a1dad3b4c3e6905c9644c6 Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 15:23:58 +0530 Subject: [PATCH 10/11] added changes --- posting/list.go | 1 - posting/mvcc.go | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/posting/list.go b/posting/list.go index ac234411b7b..a61e93b4f3e 100644 --- a/posting/list.go +++ b/posting/list.go @@ -1738,7 +1738,6 @@ func (l *List) Uids(opt ListOptions) (*pb.List, error) { } getUidList := func() (*pb.List, error, bool) { - l.calculateUids() if l.mutationMap != nil && l.mutationMap.isUidsCalculated { l.RLock() defer l.RUnlock() diff --git a/posting/mvcc.go b/posting/mvcc.go index c2c19c8124f..9b932f57ce6 100644 --- a/posting/mvcc.go +++ b/posting/mvcc.go @@ -642,6 +642,8 @@ func ReadPostingList(key []byte, it *badger.Iterator) (*List, error) { } it.Next() } + + l.calculateUids() return l, nil } From 6f2da99c140aa16cffdf6715c579abe9a23811ea Mon Sep 17 00:00:00 2001 From: Harshil Goel Date: Tue, 27 May 2025 15:26:53 +0530 Subject: [PATCH 11/11] added changes --- posting/mvcc.go | 1 + 1 file changed, 1 insertion(+) diff --git a/posting/mvcc.go b/posting/mvcc.go index 9b932f57ce6..455b29acba4 100644 --- a/posting/mvcc.go +++ b/posting/mvcc.go @@ -612,6 +612,7 @@ func ReadPostingList(key []byte, it *badger.Iterator) (*List, error) { } // No need to do Next here. The outer loop can take care of skipping // more versions of the same key. + l.calculateUids() return l, nil case BitDeltaPosting: err := item.Value(func(val []byte) error {