tsdb: sort values for Postings only when required

In the head and in v1 postings on disk, it makes no difference whether
postings are sorted. Only for v2 does the code step through in order.
So, move the sorting to where it is required, and thus skip it entirely
in the head.

Label values in on-disk blocks are already sorted, but `slices.Sort` is
very fast on already-sorted data so we don't bother checking.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
pull/11809/head
Bryan Boreham 2 years ago
parent 80ac0d7c82
commit cf92cd2688

@ -72,7 +72,7 @@ type IndexReader interface {
// Postings returns the postings list iterator for the label pairs. // Postings returns the postings list iterator for the label pairs.
// The Postings here contain the offsets to the series inside the index. // The Postings here contain the offsets to the series inside the index.
// Found IDs are not strictly required to point to a valid Series, e.g. // Found IDs are not strictly required to point to a valid Series, e.g.
// during background garbage collections. Input values must be sorted. // during background garbage collections.
Postings(name string, values ...string) (index.Postings, error) Postings(name string, values ...string) (index.Postings, error)
// SortedPostings returns a postings list that is reordered to be sorted // SortedPostings returns a postings list that is reordered to be sorted

@ -1643,6 +1643,7 @@ func (r *Reader) Postings(name string, values ...string) (Postings, error) {
return EmptyPostings(), nil return EmptyPostings(), nil
} }
slices.Sort(values) // Values must be in order so we can step through the table on disk.
res := make([]Postings, 0, len(values)) res := make([]Postings, 0, len(values))
skip := 0 skip := 0
valueIndex := 0 valueIndex := 0

@ -21,7 +21,6 @@ import (
"github.com/oklog/ulid" "github.com/oklog/ulid"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/exp/slices"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
@ -322,7 +321,6 @@ func postingsForMatcher(ix IndexReader, m *labels.Matcher) (index.Postings, erro
if m.Type == labels.MatchRegexp { if m.Type == labels.MatchRegexp {
setMatches := findSetMatches(m.GetRegexString()) setMatches := findSetMatches(m.GetRegexString())
if len(setMatches) > 0 { if len(setMatches) > 0 {
slices.Sort(setMatches)
return ix.Postings(m.Name, setMatches...) return ix.Postings(m.Name, setMatches...)
} }
} }
@ -333,14 +331,9 @@ func postingsForMatcher(ix IndexReader, m *labels.Matcher) (index.Postings, erro
} }
var res []string var res []string
lastVal, isSorted := "", true
for _, val := range vals { for _, val := range vals {
if m.Matches(val) { if m.Matches(val) {
res = append(res, val) res = append(res, val)
if isSorted && val < lastVal {
isSorted = false
}
lastVal = val
} }
} }
@ -348,9 +341,6 @@ func postingsForMatcher(ix IndexReader, m *labels.Matcher) (index.Postings, erro
return index.EmptyPostings(), nil return index.EmptyPostings(), nil
} }
if !isSorted {
slices.Sort(res)
}
return ix.Postings(m.Name, res...) return ix.Postings(m.Name, res...)
} }
@ -362,20 +352,12 @@ func inversePostingsForMatcher(ix IndexReader, m *labels.Matcher) (index.Posting
} }
var res []string var res []string
lastVal, isSorted := "", true
for _, val := range vals { for _, val := range vals {
if !m.Matches(val) { if !m.Matches(val) {
res = append(res, val) res = append(res, val)
if isSorted && val < lastVal {
isSorted = false
}
lastVal = val
} }
} }
if !isSorted {
slices.Sort(res)
}
return ix.Postings(m.Name, res...) return ix.Postings(m.Name, res...)
} }

Loading…
Cancel
Save