mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/storage: factor out getTagFilterWithMinMetricIDsCountAdaptive from updateMetricIDsForTagFilters
This commit is contained in:
parent
b4d707d9bb
commit
a1351bbaee
1 changed files with 39 additions and 34 deletions
|
@ -1164,6 +1164,39 @@ func (is *indexSearch) updateMetricIDsByMetricNameMatch(metricIDs, srcMetricIDs
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (is *indexSearch) getTagFilterWithMinMetricIDsCountAdaptive(tfs *TagFilters, maxMetrics int) (*tagFilter, map[uint64]struct{}, error) {
|
||||||
|
// Iteratively increase maxAllowedMetrics up to maxMetrics in order to limit
|
||||||
|
// the time required for founding the tag filter with minimum matching metrics.
|
||||||
|
maxAllowedMetrics := 16
|
||||||
|
if maxAllowedMetrics > maxMetrics {
|
||||||
|
maxAllowedMetrics = maxMetrics
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
minTf, minMetricIDs, err := is.getTagFilterWithMinMetricIDsCount(tfs, maxAllowedMetrics)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(minMetricIDs) < maxAllowedMetrics {
|
||||||
|
// Found the tag filter with the minimum number of metrics.
|
||||||
|
return minTf, minMetricIDs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too many metrics matched.
|
||||||
|
if maxAllowedMetrics >= maxMetrics {
|
||||||
|
// The tag filter with minimum matching metrics matches at least maxMetrics.
|
||||||
|
return nil, nil, errTooManyMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increase maxAllowedMetrics and try again.
|
||||||
|
maxAllowedMetrics *= 4
|
||||||
|
if maxAllowedMetrics > maxMetrics {
|
||||||
|
maxAllowedMetrics = maxMetrics
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errTooManyMetrics = errors.New("all the tag filters match too many metrics")
|
||||||
|
|
||||||
func (is *indexSearch) getTagFilterWithMinMetricIDsCount(tfs *TagFilters, maxMetrics int) (*tagFilter, map[uint64]struct{}, error) {
|
func (is *indexSearch) getTagFilterWithMinMetricIDsCount(tfs *TagFilters, maxMetrics int) (*tagFilter, map[uint64]struct{}, error) {
|
||||||
var minMetricIDs map[uint64]struct{}
|
var minMetricIDs map[uint64]struct{}
|
||||||
var minTf *tagFilter
|
var minTf *tagFilter
|
||||||
|
@ -1314,38 +1347,14 @@ func (is *indexSearch) updateMetricIDsForTagFilters(metricIDs map[uint64]struct{
|
||||||
// Sort tag filters for faster ts.Seek below.
|
// Sort tag filters for faster ts.Seek below.
|
||||||
sort.Slice(tfs.tfs, func(i, j int) bool { return bytes.Compare(tfs.tfs[i].prefix, tfs.tfs[j].prefix) < 0 })
|
sort.Slice(tfs.tfs, func(i, j int) bool { return bytes.Compare(tfs.tfs[i].prefix, tfs.tfs[j].prefix) < 0 })
|
||||||
|
|
||||||
// Find the filter with minimum matching metrics.
|
minTf, minMetricIDs, err := is.getTagFilterWithMinMetricIDsCountAdaptive(tfs, maxMetrics)
|
||||||
// Iteratively increase maxAllowedMetrics up to maxMetrics in order to limit
|
if err != nil {
|
||||||
// the time required for founding the tag filter with minimum matching metrics.
|
if err != errTooManyMetrics {
|
||||||
var minTf *tagFilter
|
|
||||||
var minMetricIDs map[uint64]struct{}
|
|
||||||
maxAllowedMetrics := 16
|
|
||||||
if maxAllowedMetrics > maxMetrics {
|
|
||||||
maxAllowedMetrics = maxMetrics
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
var err error
|
|
||||||
minTf, minMetricIDs, err = is.getTagFilterWithMinMetricIDsCount(tfs, maxAllowedMetrics)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(minMetricIDs) < maxAllowedMetrics {
|
|
||||||
// Found the tag filter with the minimum number of metrics.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Too many metrics matched.
|
// All the tag filters match too many metrics.
|
||||||
if maxAllowedMetrics < maxMetrics {
|
|
||||||
// Increase maxAllowedMetrics and try again.
|
|
||||||
maxAllowedMetrics *= 4
|
|
||||||
if maxAllowedMetrics > maxMetrics {
|
|
||||||
maxAllowedMetrics = maxMetrics
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// The tag filter with minimum matching metrics matches at least maxMetrics.
|
|
||||||
//
|
|
||||||
// Slow path: try filtering the matching metrics by time range.
|
// Slow path: try filtering the matching metrics by time range.
|
||||||
// This should work well for cases when old metrics are constantly substituted
|
// This should work well for cases when old metrics are constantly substituted
|
||||||
// by big number of new metrics. For example, prometheus-operator creates many new
|
// by big number of new metrics. For example, prometheus-operator creates many new
|
||||||
|
@ -1356,11 +1365,8 @@ func (is *indexSearch) updateMetricIDsForTagFilters(metricIDs map[uint64]struct{
|
||||||
maxTimeRangeMetrics := 20 * maxMetrics
|
maxTimeRangeMetrics := 20 * maxMetrics
|
||||||
metricIDsForTimeRange, err := is.getMetricIDsForTimeRange(tr, maxTimeRangeMetrics+1)
|
metricIDsForTimeRange, err := is.getMetricIDsForTimeRange(tr, maxTimeRangeMetrics+1)
|
||||||
if err == errMissingMetricIDsForDate {
|
if err == errMissingMetricIDsForDate {
|
||||||
// Give up.
|
return fmt.Errorf("cannot find tag filter matching less up to %d time series; either increase -search.maxUniqueTimeseries or use more specific tag filters",
|
||||||
for metricID := range minMetricIDs {
|
maxMetrics)
|
||||||
metricIDs[metricID] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1371,7 +1377,6 @@ func (is *indexSearch) updateMetricIDsForTagFilters(metricIDs map[uint64]struct{
|
||||||
}
|
}
|
||||||
minMetricIDs = metricIDsForTimeRange
|
minMetricIDs = metricIDsForTimeRange
|
||||||
minTf = nil
|
minTf = nil
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find intersection of minTf with other tfs.
|
// Find intersection of minTf with other tfs.
|
||||||
|
|
Loading…
Reference in a new issue