mirror of
https://github.com/hanzoai/metrics.git
synced 2026-10-30 20:03:39 +00:00
This should reduce disk space occupied by indexDBs as they get deleted along with the corresponding partitions once those partitions become outside the retention window. - Motivation: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7599 - What to expect: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8134 Signed-off-by: Artem Fetishev <[email protected]> Co-authored-by: Andrei Baidarov <[email protected]>
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
// metricNameSearch is used for searching a metricName by a metricID in
|
|
// partition and legacy indexDBs. If useSparseCache is false the name is first
|
|
// searched in metricNameCache and also stored in that cache when found in one
|
|
// of the indexDBs.
|
|
//
|
|
// Most index search methods invoked only once per API call. For example, one
|
|
// request to /api/v1/series results in one invocation of
|
|
// Storage.SearchMetricNames() method. However, searching a metricName by
|
|
// metricID is done multiple times per API call. For example, data search
|
|
// performs the metricName search for each data block (see search.go).
|
|
//
|
|
// Additionally, each search method must get a snapshot of idbs so that they
|
|
// don't get rotated in the middle of the search. This works for methods that
|
|
// are invoked only once per API call. But for searching metricName by metricID
|
|
// happens many times per API call and the idb snapshot must be taken
|
|
// outside the search method.
|
|
//
|
|
// To address this, the state of the metricNameSearch type holds the search
|
|
// context: the idb snapshot along with other options. This not only ensures
|
|
// that idbs won't change during the API call but also avoids performance
|
|
// degradation that may be caused by getting the idb snapshot every time the
|
|
// search method is invoked (due do mutex locks).
|
|
type metricNameSearch struct {
|
|
storage *Storage
|
|
ptws []*partitionWrapper
|
|
idbs []*indexDB
|
|
legacyIDBs *legacyIndexDBs
|
|
useSparseCache bool
|
|
}
|
|
|
|
// search searches the metricName of a metricID.
|
|
func (s *metricNameSearch) search(dst []byte, metricID uint64) ([]byte, bool) {
|
|
if !s.useSparseCache {
|
|
n := len(dst)
|
|
dst = s.storage.getMetricNameFromCache(dst, metricID)
|
|
if len(dst) > n {
|
|
return dst, true
|
|
}
|
|
}
|
|
|
|
var found bool
|
|
|
|
// This will be just one idb most of the time since a typical time range
|
|
// fits within a single month.
|
|
for _, idb := range s.idbs {
|
|
dst, found = idb.searchMetricName(dst, metricID, s.useSparseCache)
|
|
if found {
|
|
if !s.useSparseCache {
|
|
s.storage.putMetricNameToCache(metricID, dst)
|
|
}
|
|
return dst, true
|
|
}
|
|
}
|
|
|
|
// Fallback to current legacy indexDB.
|
|
if idb := s.legacyIDBs.getIDBCurr(); idb != nil {
|
|
dst, found = idb.searchMetricName(dst, metricID, s.useSparseCache)
|
|
if found {
|
|
if !s.useSparseCache {
|
|
s.storage.putMetricNameToCache(metricID, dst)
|
|
}
|
|
return dst, true
|
|
}
|
|
}
|
|
|
|
// Fallback to previous legacy indexDB.
|
|
if idb := s.legacyIDBs.getIDBPrev(); idb != nil {
|
|
dst, found = idb.searchMetricName(dst, metricID, s.useSparseCache)
|
|
if found {
|
|
if !s.useSparseCache {
|
|
s.storage.putMetricNameToCache(metricID, dst)
|
|
}
|
|
return dst, true
|
|
}
|
|
}
|
|
|
|
// Not deleting metricID if no corresponding metricName has been found
|
|
// because it is not known which indexDB metricID belongs to.
|
|
// For cases when this does happen see indexDB.SearchMetricNames() and
|
|
// indexDB.SearchTSIDs().
|
|
|
|
return dst, false
|
|
}
|
|
|
|
var mnsPool = &sync.Pool{
|
|
New: func() any {
|
|
return &metricNameSearch{}
|
|
},
|
|
}
|
|
|
|
func getMetricNameSearch(storage *Storage, tr TimeRange, useSparseCache bool) *metricNameSearch {
|
|
s := mnsPool.Get().(*metricNameSearch)
|
|
s.storage = storage
|
|
s.ptws = storage.tb.GetPartitions(tr)
|
|
for _, ptw := range s.ptws {
|
|
s.idbs = append(s.idbs, ptw.pt.idb)
|
|
}
|
|
s.legacyIDBs = storage.getLegacyIndexDBs()
|
|
s.useSparseCache = useSparseCache
|
|
return s
|
|
}
|
|
|
|
func putMetricNameSearch(s *metricNameSearch) {
|
|
s.storage.tb.PutPartitions(s.ptws)
|
|
s.storage.putLegacyIndexDBs(s.legacyIDBs)
|
|
s.storage = nil
|
|
s.ptws = nil
|
|
s.idbs = nil
|
|
s.legacyIDBs = nil
|
|
s.useSparseCache = false
|
|
mnsPool.Put(s)
|
|
}
|