lib/storage: increase match cost for negative tag filters, since they need to scan all the label pairs

This commit is contained in:
Aliaksandr Valialkin 2021-02-15 16:24:08 +02:00
parent 46e98ed490
commit 3eae03a337
2 changed files with 15 additions and 1 deletions

View File

@ -2829,7 +2829,7 @@ func (is *indexSearch) getMetricIDsForDateAndFilters(date uint64, tfs *TagFilter
if a.seconds != b.seconds {
return a.seconds < b.seconds
}
return a.tf.matchCost < b.tf.matchCost
return a.tf.Less(b.tf)
})
// Populate metricIDs for the first non-negative filter.

View File

@ -252,6 +252,9 @@ type tagFilter struct {
func (tf *tagFilter) Less(other *tagFilter) bool {
// Move regexp and negative filters to the end, since they require scanning
// all the entries for the given label.
if tf.matchCost != other.matchCost {
return tf.matchCost < other.matchCost
}
if tf.isRegexp != other.isRegexp {
return !tf.isRegexp
}
@ -330,6 +333,9 @@ func (tf *tagFilter) InitFromGraphiteQuery(commonPrefix, query []byte, paths []s
tf.prefix = marshalTagValueNoTrailingTagSeparator(tf.prefix, []byte(prefix))
tf.orSuffixes = append(tf.orSuffixes[:0], orSuffixes...)
tf.reSuffixMatch, tf.matchCost = newMatchFuncForOrSuffixes(orSuffixes)
if isNegative {
tf.matchCost *= negativeMatchCostMultiplier
}
}
func getCommonPrefix(ss []string) (string, []string) {
@ -397,6 +403,9 @@ func (tf *tagFilter) Init(commonPrefix, key, value []byte, isNegative, isRegexp
tf.orSuffixes = append(tf.orSuffixes[:0], "")
tf.isEmptyMatch = len(prefix) == 0
tf.matchCost = fullMatchCost
if isNegative {
tf.matchCost *= negativeMatchCostMultiplier
}
return nil
}
rcv, err := getRegexpFromCache(expr)
@ -406,6 +415,9 @@ func (tf *tagFilter) Init(commonPrefix, key, value []byte, isNegative, isRegexp
tf.orSuffixes = append(tf.orSuffixes[:0], rcv.orValues...)
tf.reSuffixMatch = rcv.reMatch
tf.matchCost = rcv.reCost
if isNegative {
tf.matchCost *= negativeMatchCostMultiplier
}
tf.isEmptyMatch = len(prefix) == 0 && tf.reSuffixMatch(nil)
if !tf.isNegative && len(key) == 0 && strings.IndexByte(rcv.literalSuffix, '.') >= 0 {
// Reverse suffix is needed only for non-negative regexp filters on __name__ that contains dots.
@ -577,6 +589,8 @@ const (
reMatchCost = 100
)
const negativeMatchCostMultiplier = 1000
func getOptimizedReMatchFuncExt(reMatch func(b []byte) bool, sre *syntax.Regexp) (func(b []byte) bool, string, uint64) {
if isDotStar(sre) {
// '.*'