From cc9072ad649518bc77f818758f7a7a2f64219ab8 Mon Sep 17 00:00:00 2001 From: Patrick Oyarzun Date: Mon, 17 Apr 2023 19:58:56 -0500 Subject: [PATCH 1/2] Apply matchers when fetching label values --- tsdb/querier.go | 18 ++++++++++++++++++ tsdb/querier_bench_test.go | 1 + 2 files changed, 19 insertions(+) diff --git a/tsdb/querier.go b/tsdb/querier.go index aed4952ac0..a8a18164aa 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -338,6 +338,24 @@ func labelValuesWithMatchers(r IndexReader, name string, matchers ...*labels.Mat if err != nil { return nil, errors.Wrapf(err, "fetching values of label %s", name) } + + // If we have a matcher for the label name, we can filter out values that don't match + // before we fetch postings. This is especially useful for labels with many values. + // e.g. __name__ with a selector like {__name__="xyz"} + for _, m := range matchers { + if m.Name != name { + continue + } + + for i := len(allValues) - 1; i >= 0; i-- { + if m.Matches(allValues[i]) { + continue + } + + allValues = append(allValues[:i], allValues[i+1:]...) + } + } + valuesPostings := make([]index.Postings, len(allValues)) for i, value := range allValues { valuesPostings[i], err = r.Postings(name, value) diff --git a/tsdb/querier_bench_test.go b/tsdb/querier_bench_test.go index bd8f7131cf..741301dca6 100644 --- a/tsdb/querier_bench_test.go +++ b/tsdb/querier_bench_test.go @@ -182,6 +182,7 @@ func benchmarkLabelValuesWithMatchers(b *testing.B, ir IndexReader) { labelName string matchers []*labels.Matcher }{ + {`i with i="1"`, "i", []*labels.Matcher{i1}}, // i has 100k values. {`i with n="1"`, "i", []*labels.Matcher{n1}}, {`i with n="^.+$"`, "i", []*labels.Matcher{nPlus}}, From e52ce3e361239e5dfe6045787de9a161319a675b Mon Sep 17 00:00:00 2001 From: Patrick Oyarzun Date: Tue, 18 Apr 2023 15:50:05 -0500 Subject: [PATCH 2/2] Avoid extra copying of label values --- tsdb/querier.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tsdb/querier.go b/tsdb/querier.go index a8a18164aa..1e6a817afb 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -347,13 +347,15 @@ func labelValuesWithMatchers(r IndexReader, name string, matchers ...*labels.Mat continue } - for i := len(allValues) - 1; i >= 0; i-- { - if m.Matches(allValues[i]) { - continue + // re-use the allValues slice to avoid allocations + // this is safe because the iteration is always ahead of the append + filteredValues := allValues[:0] + for _, v := range allValues { + if m.Matches(v) { + filteredValues = append(filteredValues, v) } - - allValues = append(allValues[:i], allValues[i+1:]...) } + allValues = filteredValues } valuesPostings := make([]index.Postings, len(allValues))