From 6b1cc9b94644f2179ac47bf1f78ace181245587e Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Thu, 18 Apr 2024 20:29:33 +0200 Subject: [PATCH] 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 66630c7960222b0afeaa3c69327225d16f75c502 --- lib/storage/storage.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/storage/storage.go b/lib/storage/storage.go index 4e8c4c7a3f..c3f050f2cc 100644 --- a/lib/storage/storage.go +++ b/lib/storage/storage.go @@ -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 { // 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. - lvs, err := idb.SearchLabelValuesWithFiltersOnTimeRange(qt, labelName, nil, tr, maxLabelValues, maxMetrics, deadline) + // without any filters and limits and then later applying the filter and the limit to the found label values. + 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 { return nil, err } + needSlowSearch := len(lvs) == maxMetrics + + lvsLen := len(lvs) 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)