lib/storage: search for all the values for the given label before applying filters and limits

It is incorrect applying the limit on the number of values to search without applying filters,
since the returned subset of label values may miss the label values matching the given filters.

This is a follow-up for 66630c7960
This commit is contained in:
Aliaksandr Valialkin 2024-04-18 20:29:33 +02:00
parent d3635aae7f
commit 6b1cc9b946
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB

View file

@ -1290,13 +1290,29 @@ func (s *Storage) SearchLabelValuesWithFiltersOnTimeRange(qt *querytracer.Tracer
} }
if len(tfss) == 1 && len(tfss[0].tfs) == 1 && string(tfss[0].tfs[0].key) == key { if len(tfss) == 1 && len(tfss[0].tfs) == 1 && string(tfss[0].tfs[0].key) == key {
// tfss contains only a single filter on labelName. It is faster searching for label values // tfss contains only a single filter on labelName. It is faster searching for label values
// without any filters and then later applying the filter to the found label values. // without any filters and limits and then later applying the filter and the limit to the found label values.
lvs, err := idb.SearchLabelValuesWithFiltersOnTimeRange(qt, labelName, nil, tr, maxLabelValues, maxMetrics, deadline) qt.Printf("search for up to %d values for the label %q on the time range %s", maxMetrics, labelName, &tr)
lvs, err := idb.SearchLabelValuesWithFiltersOnTimeRange(qt, labelName, nil, tr, maxMetrics, maxMetrics, deadline)
if err != nil { if err != nil {
return nil, err return nil, err
} }
needSlowSearch := len(lvs) == maxMetrics
lvsLen := len(lvs)
lvs = filterLabelValues(lvs, &tfss[0].tfs[0], key) lvs = filterLabelValues(lvs, &tfss[0].tfs[0], key)
return lvs, nil qt.Printf("found %d out of %d values for the label %q after filtering", len(lvs), lvsLen, labelName)
if len(lvs) >= maxLabelValues {
qt.Printf("leave %d out of %d values for the label %q because of the limit", maxLabelValues, len(lvs), labelName)
lvs = lvs[:maxLabelValues]
// We found at least maxLabelValues unique values for the label with the given filters.
// It is OK returning all these values instead of falling back to the slow search.
needSlowSearch = false
}
if !needSlowSearch {
return lvs, nil
}
qt.Printf("fall back to slow search because only a subset of label values is found")
} }
return idb.SearchLabelValuesWithFiltersOnTimeRange(qt, labelName, tfss, tr, maxLabelValues, maxMetrics, deadline) return idb.SearchLabelValuesWithFiltersOnTimeRange(qt, labelName, tfss, tr, maxLabelValues, maxMetrics, deadline)