Skip to content

Commit 98dee9f

Browse files
authored
Merge pull request #377 from grafana/shortcut-postings-for-matchers
Shortcut postings for matchers when empty postings are selected
2 parents 6fc69c8 + e246ce4 commit 98dee9f

4 files changed

Lines changed: 38 additions & 1 deletion

File tree

tsdb/head_read.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ func (h *headIndexReader) Postings(name string, values ...string) (index.Posting
113113
default:
114114
res := make([]index.Postings, 0, len(values))
115115
for _, value := range values {
116-
res = append(res, h.head.postings.Get(name, value))
116+
if p := h.head.postings.Get(name, value); !index.IsEmptyPostingsType(p) {
117+
res = append(res, p)
118+
}
117119
}
118120
return index.Merge(res...), nil
119121
}

tsdb/index/postings.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,13 @@ func EmptyPostings() Postings {
428428
return emptyPostings
429429
}
430430

431+
// IsEmptyPostingsType returns true if the postings are an empty postings list.
432+
// When this function returns false, it doesn't mean that the postings isn't empty
433+
// (it could be an empty intersection of two non-empty postings, for example).
434+
func IsEmptyPostingsType(p Postings) bool {
435+
return p == emptyPostings
436+
}
437+
431438
// ErrPostings returns new postings that immediately error.
432439
func ErrPostings(err error) Postings {
433440
return errPostings{err}

tsdb/querier.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,19 @@ func PostingsForMatchers(ix IndexPostingsReader, ms ...*labels.Matcher) (index.P
215215
if err != nil {
216216
return nil, err
217217
}
218+
if index.IsEmptyPostingsType(it) {
219+
return index.EmptyPostings(), nil
220+
}
218221
its = append(its, it)
219222
} else { // l="a"
220223
// Non-Not matcher, use normal postingsForMatcher.
221224
it, err := postingsForMatcher(ix, m)
222225
if err != nil {
223226
return nil, err
224227
}
228+
if index.IsEmptyPostingsType(it) {
229+
return index.EmptyPostings(), nil
230+
}
225231
its = append(its, it)
226232
}
227233
} else { // l=""

tsdb/querier_bench_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ func BenchmarkQuerier(b *testing.B) {
9393

9494
func benchmarkPostingsForMatchers(b *testing.B, ir IndexReader) {
9595
n1 := labels.MustNewMatcher(labels.MatchEqual, "n", "1"+postingsBenchSuffix)
96+
nX := labels.MustNewMatcher(labels.MatchNotEqual, "n", "X"+postingsBenchSuffix)
9697

9798
jFoo := labels.MustNewMatcher(labels.MatchEqual, "j", "foo")
9899
jNotFoo := labels.MustNewMatcher(labels.MatchNotEqual, "j", "foo")
@@ -109,35 +110,50 @@ func benchmarkPostingsForMatchers(b *testing.B, ir IndexReader) {
109110
iNot2Star := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "^2.*$")
110111
iNotStar2Star := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "^.*2.*$")
111112
jFooBar := labels.MustNewMatcher(labels.MatchRegexp, "j", "foo|bar")
113+
jXXXYYY := labels.MustNewMatcher(labels.MatchRegexp, "j", "XXX|YYY")
114+
jXplus := labels.MustNewMatcher(labels.MatchRegexp, "j", "X.+")
112115
iCharSet := labels.MustNewMatcher(labels.MatchRegexp, "i", "1[0-9]")
113116
iAlternate := labels.MustNewMatcher(labels.MatchRegexp, "i", "(1|2|3|4|5|6|20|55)")
117+
iXYZ := labels.MustNewMatcher(labels.MatchRegexp, "i", "X|Y|Z")
114118
cases := []struct {
115119
name string
116120
matchers []*labels.Matcher
117121
}{
118122
{`n="1"`, []*labels.Matcher{n1}},
123+
{`n="X"`, []*labels.Matcher{nX}},
119124
{`n="1",j="foo"`, []*labels.Matcher{n1, jFoo}},
125+
{`n="X",j="foo"`, []*labels.Matcher{nX, jFoo}},
120126
{`j="foo",n="1"`, []*labels.Matcher{jFoo, n1}},
121127
{`n="1",j!="foo"`, []*labels.Matcher{n1, jNotFoo}},
128+
{`n="X",j!="foo"`, []*labels.Matcher{nX, jNotFoo}},
122129
{`i=~"1[0-9]",j=~"foo|bar"`, []*labels.Matcher{iCharSet, jFooBar}},
123130
{`j=~"foo|bar"`, []*labels.Matcher{jFooBar}},
131+
{`j=~"XXX|YYY"`, []*labels.Matcher{jXXXYYY}},
132+
{`j=~"X.+"`, []*labels.Matcher{jXplus}},
124133
{`i=~"(1|2|3|4|5|6|20|55)"`, []*labels.Matcher{iAlternate}},
134+
{`i=~"X|Y|Z"`, []*labels.Matcher{iXYZ}},
125135
{`i=~".*"`, []*labels.Matcher{iStar}},
126136
{`i=~"1.*"`, []*labels.Matcher{i1Star}},
127137
{`i=~".*1"`, []*labels.Matcher{iStar1}},
128138
{`i=~".+"`, []*labels.Matcher{iPlus}},
139+
{`i=~".+",j=~"X.+"`, []*labels.Matcher{iPlus, jXplus}},
129140
{`i=~""`, []*labels.Matcher{iEmptyRe}},
130141
{`i!=""`, []*labels.Matcher{iNotEmpty}},
131142
{`n="1",i=~".*",j="foo"`, []*labels.Matcher{n1, iStar, jFoo}},
143+
{`n="X",i=~".*",j="foo"`, []*labels.Matcher{nX, iStar, jFoo}},
132144
{`n="1",i=~".*",i!="2",j="foo"`, []*labels.Matcher{n1, iStar, iNot2, jFoo}},
133145
{`n="1",i!=""`, []*labels.Matcher{n1, iNotEmpty}},
134146
{`n="1",i!="",j="foo"`, []*labels.Matcher{n1, iNotEmpty, jFoo}},
147+
{`n="1",i!="",j=~"X.+"`, []*labels.Matcher{n1, iNotEmpty, jXplus}},
148+
{`n="1",i!="",j=~"XXX|YYY"`, []*labels.Matcher{n1, iNotEmpty, jXXXYYY}},
149+
{`n="1",i=~"X|Y|Z",j="foo"`, []*labels.Matcher{n1, iXYZ, jFoo}},
135150
{`n="1",i=~".+",j="foo"`, []*labels.Matcher{n1, iPlus, jFoo}},
136151
{`n="1",i=~"1.+",j="foo"`, []*labels.Matcher{n1, i1Plus, jFoo}},
137152
{`n="1",i=~".*1.*",j="foo"`, []*labels.Matcher{n1, iStar1Star, jFoo}},
138153
{`n="1",i=~".+",i!="2",j="foo"`, []*labels.Matcher{n1, iPlus, iNot2, jFoo}},
139154
{`n="1",i=~".+",i!~"2.*",j="foo"`, []*labels.Matcher{n1, iPlus, iNot2Star, jFoo}},
140155
{`n="1",i=~".+",i!~".*2.*",j="foo"`, []*labels.Matcher{n1, iPlus, iNotStar2Star, jFoo}},
156+
{`n="X",i=~".+",i!~".*2.*",j="foo"`, []*labels.Matcher{nX, iPlus, iNotStar2Star, jFoo}},
141157
}
142158

143159
for _, c := range cases {
@@ -154,7 +170,10 @@ func benchmarkLabelValuesWithMatchers(b *testing.B, ir IndexReader) {
154170
i1 := labels.MustNewMatcher(labels.MatchEqual, "i", "1")
155171
iStar := labels.MustNewMatcher(labels.MatchRegexp, "i", "^.*$")
156172
jNotFoo := labels.MustNewMatcher(labels.MatchNotEqual, "j", "foo")
173+
jXXXYYY := labels.MustNewMatcher(labels.MatchRegexp, "j", "XXX|YYY")
174+
jXplus := labels.MustNewMatcher(labels.MatchRegexp, "j", "X.+")
157175
n1 := labels.MustNewMatcher(labels.MatchEqual, "n", "1"+postingsBenchSuffix)
176+
nX := labels.MustNewMatcher(labels.MatchNotEqual, "n", "X"+postingsBenchSuffix)
158177
nPlus := labels.MustNewMatcher(labels.MatchRegexp, "i", "^.+$")
159178

160179
cases := []struct {
@@ -166,6 +185,9 @@ func benchmarkLabelValuesWithMatchers(b *testing.B, ir IndexReader) {
166185
{`i with n="1"`, "i", []*labels.Matcher{n1}},
167186
{`i with n="^.+$"`, "i", []*labels.Matcher{nPlus}},
168187
{`i with n="1",j!="foo"`, "i", []*labels.Matcher{n1, jNotFoo}},
188+
{`i with n="1",j=~"X.+"`, "i", []*labels.Matcher{n1, jXplus}},
189+
{`i with n="1",j=~"XXX|YYY"`, "i", []*labels.Matcher{n1, jXXXYYY}},
190+
{`i with n="X",j!="foo"`, "i", []*labels.Matcher{nX, jNotFoo}},
169191
{`i with n="1",i=~"^.*$",j!="foo"`, "i", []*labels.Matcher{n1, iStar, jNotFoo}},
170192
// n has 10 values.
171193
{`n with j!="foo"`, "n", []*labels.Matcher{jNotFoo}},

0 commit comments

Comments
 (0)