Apply relevant label matchers in LabelValues before fetching extra postings (#12274)

* Apply matchers when fetching label values

Signed-off-by: Patrick Oyarzun <patrick.oyarzun@grafana.com>

* Avoid extra copying of label values

Signed-off-by: Patrick Oyarzun <patrick.oyarzun@grafana.com>

---------

Signed-off-by: Patrick Oyarzun <patrick.oyarzun@grafana.com>
This commit is contained in:
Patrick Oyarzun 2023-07-04 04:37:58 -05:00 committed by GitHub
parent 031d22df9e
commit 68e5937474
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 0 deletions

View file

@ -414,6 +414,26 @@ 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
}
// 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 = filteredValues
}
valuesPostings := make([]index.Postings, len(allValues))
for i, value := range allValues {
valuesPostings[i], err = r.Postings(name, value)

View file

@ -188,6 +188,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}},