mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/storage: increase match cost for negative tag filters, since they need to scan all the label pairs
This commit is contained in:
parent
4e39bf148c
commit
ecf132933e
2 changed files with 15 additions and 1 deletions
|
@ -2804,7 +2804,7 @@ func (is *indexSearch) getMetricIDsForDateAndFilters(date uint64, tfs *TagFilter
|
||||||
if a.seconds != b.seconds {
|
if a.seconds != b.seconds {
|
||||||
return 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.
|
// Populate metricIDs for the first non-negative filter.
|
||||||
|
|
|
@ -240,6 +240,9 @@ type tagFilter struct {
|
||||||
func (tf *tagFilter) Less(other *tagFilter) bool {
|
func (tf *tagFilter) Less(other *tagFilter) bool {
|
||||||
// Move regexp and negative filters to the end, since they require scanning
|
// Move regexp and negative filters to the end, since they require scanning
|
||||||
// all the entries for the given label.
|
// all the entries for the given label.
|
||||||
|
if tf.matchCost != other.matchCost {
|
||||||
|
return tf.matchCost < other.matchCost
|
||||||
|
}
|
||||||
if tf.isRegexp != other.isRegexp {
|
if tf.isRegexp != other.isRegexp {
|
||||||
return !tf.isRegexp
|
return !tf.isRegexp
|
||||||
}
|
}
|
||||||
|
@ -312,6 +315,9 @@ func (tf *tagFilter) InitFromGraphiteQuery(commonPrefix, query []byte, paths []s
|
||||||
tf.prefix = marshalTagValueNoTrailingTagSeparator(tf.prefix, []byte(prefix))
|
tf.prefix = marshalTagValueNoTrailingTagSeparator(tf.prefix, []byte(prefix))
|
||||||
tf.orSuffixes = append(tf.orSuffixes[:0], orSuffixes...)
|
tf.orSuffixes = append(tf.orSuffixes[:0], orSuffixes...)
|
||||||
tf.reSuffixMatch, tf.matchCost = newMatchFuncForOrSuffixes(orSuffixes)
|
tf.reSuffixMatch, tf.matchCost = newMatchFuncForOrSuffixes(orSuffixes)
|
||||||
|
if isNegative {
|
||||||
|
tf.matchCost *= negativeMatchCostMultiplier
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCommonPrefix(ss []string) (string, []string) {
|
func getCommonPrefix(ss []string) (string, []string) {
|
||||||
|
@ -379,6 +385,9 @@ func (tf *tagFilter) Init(commonPrefix, key, value []byte, isNegative, isRegexp
|
||||||
tf.orSuffixes = append(tf.orSuffixes[:0], "")
|
tf.orSuffixes = append(tf.orSuffixes[:0], "")
|
||||||
tf.isEmptyMatch = len(prefix) == 0
|
tf.isEmptyMatch = len(prefix) == 0
|
||||||
tf.matchCost = fullMatchCost
|
tf.matchCost = fullMatchCost
|
||||||
|
if isNegative {
|
||||||
|
tf.matchCost *= negativeMatchCostMultiplier
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
rcv, err := getRegexpFromCache(expr)
|
rcv, err := getRegexpFromCache(expr)
|
||||||
|
@ -388,6 +397,9 @@ func (tf *tagFilter) Init(commonPrefix, key, value []byte, isNegative, isRegexp
|
||||||
tf.orSuffixes = append(tf.orSuffixes[:0], rcv.orValues...)
|
tf.orSuffixes = append(tf.orSuffixes[:0], rcv.orValues...)
|
||||||
tf.reSuffixMatch = rcv.reMatch
|
tf.reSuffixMatch = rcv.reMatch
|
||||||
tf.matchCost = rcv.reCost
|
tf.matchCost = rcv.reCost
|
||||||
|
if isNegative {
|
||||||
|
tf.matchCost *= negativeMatchCostMultiplier
|
||||||
|
}
|
||||||
tf.isEmptyMatch = len(prefix) == 0 && tf.reSuffixMatch(nil)
|
tf.isEmptyMatch = len(prefix) == 0 && tf.reSuffixMatch(nil)
|
||||||
if !tf.isNegative && len(key) == 0 && strings.IndexByte(rcv.literalSuffix, '.') >= 0 {
|
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.
|
// Reverse suffix is needed only for non-negative regexp filters on __name__ that contains dots.
|
||||||
|
@ -559,6 +571,8 @@ const (
|
||||||
reMatchCost = 100
|
reMatchCost = 100
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const negativeMatchCostMultiplier = 1000
|
||||||
|
|
||||||
func getOptimizedReMatchFuncExt(reMatch func(b []byte) bool, sre *syntax.Regexp) (func(b []byte) bool, string, uint64) {
|
func getOptimizedReMatchFuncExt(reMatch func(b []byte) bool, sre *syntax.Regexp) (func(b []byte) bool, string, uint64) {
|
||||||
if isDotStar(sre) {
|
if isDotStar(sre) {
|
||||||
// '.*'
|
// '.*'
|
||||||
|
|
Loading…
Reference in a new issue