Only do regex lookups when there was no equality match.
For the label matching index-based preselection phase, don't do an OR between equality and non-equality matchers. Execute only one of the two (with equality matchers preferred when present). Fixes https://github.com/prometheus/prometheus/issues/924
This commit is contained in:
parent
a59b7ac7f8
commit
517badc21d
|
@ -428,39 +428,40 @@ func (s *memorySeriesStorage) MetricsForLabelMatchers(matchers ...*metric.LabelM
|
||||||
}
|
}
|
||||||
|
|
||||||
var resFPs map[clientmodel.Fingerprint]struct{}
|
var resFPs map[clientmodel.Fingerprint]struct{}
|
||||||
// If we cannot make a preselection based on equality matchers, expanding the other matchers to labels
|
|
||||||
// and intersecting their fingerprints is still likely to be the best choice.
|
|
||||||
if len(equals) > 0 {
|
if len(equals) > 0 {
|
||||||
resFPs = s.fingerprintsForLabelPairs(equals...)
|
resFPs = s.fingerprintsForLabelPairs(equals...)
|
||||||
}
|
} else {
|
||||||
var remaining metric.LabelMatchers
|
// If we cannot make a preselection based on equality matchers, expanding the other matchers to labels
|
||||||
for _, matcher := range filters {
|
// and intersecting their fingerprints is still likely to be the best choice.
|
||||||
// Equal matches are all empty values.
|
var remaining metric.LabelMatchers
|
||||||
if matcher.Match("") {
|
for _, matcher := range filters {
|
||||||
remaining = append(remaining, matcher)
|
// Equal matches are all empty values.
|
||||||
continue
|
if matcher.Match("") {
|
||||||
}
|
remaining = append(remaining, matcher)
|
||||||
intersection := map[clientmodel.Fingerprint]struct{}{}
|
continue
|
||||||
|
}
|
||||||
|
intersection := map[clientmodel.Fingerprint]struct{}{}
|
||||||
|
|
||||||
matches := matcher.Filter(s.LabelValuesForLabelName(matcher.Name))
|
matches := matcher.Filter(s.LabelValuesForLabelName(matcher.Name))
|
||||||
if len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, v := range matches {
|
for _, v := range matches {
|
||||||
fps := s.fingerprintsForLabelPairs(metric.LabelPair{
|
fps := s.fingerprintsForLabelPairs(metric.LabelPair{
|
||||||
Name: matcher.Name,
|
Name: matcher.Name,
|
||||||
Value: v,
|
Value: v,
|
||||||
})
|
})
|
||||||
for fp := range fps {
|
for fp := range fps {
|
||||||
if _, ok := resFPs[fp]; ok || resFPs == nil {
|
if _, ok := resFPs[fp]; ok || resFPs == nil {
|
||||||
intersection[fp] = struct{}{}
|
intersection[fp] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resFPs = intersection
|
||||||
}
|
}
|
||||||
resFPs = intersection
|
// The intersected matchers no longer need to be compared against the actual metrics.
|
||||||
|
filters = remaining
|
||||||
}
|
}
|
||||||
// The intersected matchers no longer need to be compared against the actual metrics.
|
|
||||||
filters = remaining
|
|
||||||
|
|
||||||
result := make(map[clientmodel.Fingerprint]clientmodel.COWMetric, len(resFPs))
|
result := make(map[clientmodel.Fingerprint]clientmodel.COWMetric, len(resFPs))
|
||||||
for fp := range resFPs {
|
for fp := range resFPs {
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestMatches(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
matchers: metric.LabelMatchers{newMatcher(metric.Equal, "label1", "x")},
|
matchers: metric.LabelMatchers{newMatcher(metric.Equal, "label1", "x")},
|
||||||
expected: fingerprints[:0],
|
expected: clientmodel.Fingerprints{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
matchers: metric.LabelMatchers{newMatcher(metric.Equal, "label1", "test_0")},
|
matchers: metric.LabelMatchers{newMatcher(metric.Equal, "label1", "test_0")},
|
||||||
|
@ -161,6 +161,20 @@ func TestMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
expected: append(append(clientmodel.Fingerprints{}, fingerprints[30:35]...), fingerprints[45:60]...),
|
expected: append(append(clientmodel.Fingerprints{}, fingerprints[30:35]...), fingerprints[45:60]...),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
matchers: metric.LabelMatchers{
|
||||||
|
newMatcher(metric.Equal, "label1", `nonexistent`),
|
||||||
|
newMatcher(metric.RegexMatch, "label2", `test`),
|
||||||
|
},
|
||||||
|
expected: clientmodel.Fingerprints{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchers: metric.LabelMatchers{
|
||||||
|
newMatcher(metric.Equal, "label1", `test_0`),
|
||||||
|
newMatcher(metric.RegexMatch, "label2", `nonexistent`),
|
||||||
|
},
|
||||||
|
expected: clientmodel.Fingerprints{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mt := range matcherTests {
|
for _, mt := range matcherTests {
|
||||||
|
|
Loading…
Reference in New Issue