mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-31 15:06:26 +00:00
wip
This commit is contained in:
parent
ba40c1a2d5
commit
e391d7b69c
1 changed files with 112 additions and 0 deletions
|
@ -2,6 +2,7 @@ package logstorage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// filterOr contains filters joined by OR operator.
|
// filterOr contains filters joined by OR operator.
|
||||||
|
@ -9,6 +10,9 @@ import (
|
||||||
// It is epxressed as `f1 OR f2 ... OR fN` in LogsQL.
|
// It is epxressed as `f1 OR f2 ... OR fN` in LogsQL.
|
||||||
type filterOr struct {
|
type filterOr struct {
|
||||||
filters []filter
|
filters []filter
|
||||||
|
|
||||||
|
byFieldTokensOnce sync.Once
|
||||||
|
byFieldTokens []fieldTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fo *filterOr) String() string {
|
func (fo *filterOr) String() string {
|
||||||
|
@ -51,6 +55,12 @@ func (fo *filterOr) applyToBlockResult(br *blockResult, bm *bitmap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fo *filterOr) applyToBlockSearch(bs *blockSearch, bm *bitmap) {
|
func (fo *filterOr) applyToBlockSearch(bs *blockSearch, bm *bitmap) {
|
||||||
|
if !fo.matchBloomFilters(bs) {
|
||||||
|
// Fast path - fo doesn't match bloom filters.
|
||||||
|
bm.resetBits()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
bmResult := getBitmap(bm.bitsLen)
|
bmResult := getBitmap(bm.bitsLen)
|
||||||
bmTmp := getBitmap(bm.bitsLen)
|
bmTmp := getBitmap(bm.bitsLen)
|
||||||
for _, f := range fo.filters {
|
for _, f := range fo.filters {
|
||||||
|
@ -72,3 +82,105 @@ func (fo *filterOr) applyToBlockSearch(bs *blockSearch, bm *bitmap) {
|
||||||
bm.copyFrom(bmResult)
|
bm.copyFrom(bmResult)
|
||||||
putBitmap(bmResult)
|
putBitmap(bmResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fo *filterOr) matchBloomFilters(bs *blockSearch) bool {
|
||||||
|
byFieldTokens := fo.getByFieldTokens()
|
||||||
|
if len(byFieldTokens) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fieldTokens := range byFieldTokens {
|
||||||
|
fieldName := fieldTokens.field
|
||||||
|
tokens := fieldTokens.tokens
|
||||||
|
|
||||||
|
v := bs.csh.getConstColumnValue(fieldName)
|
||||||
|
if v != "" {
|
||||||
|
if matchStringByAllTokens(v, tokens) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := bs.csh.getColumnHeader(fieldName)
|
||||||
|
if ch == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch.valueType == valueTypeDict {
|
||||||
|
if matchDictValuesByAllTokens(ch.valuesDict.values, tokens) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if matchBloomFilterAllTokens(bs, ch, tokens) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fo *filterOr) getByFieldTokens() []fieldTokens {
|
||||||
|
fo.byFieldTokensOnce.Do(fo.initByFieldTokens)
|
||||||
|
return fo.byFieldTokens
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fo *filterOr) initByFieldTokens() {
|
||||||
|
m := make(map[string][][]string)
|
||||||
|
byFieldFilters := make(map[string]int)
|
||||||
|
var fieldNames []string
|
||||||
|
|
||||||
|
for _, f := range fo.filters {
|
||||||
|
fieldName := ""
|
||||||
|
var tokens []string
|
||||||
|
|
||||||
|
switch t := f.(type) {
|
||||||
|
case *filterExact:
|
||||||
|
fieldName = t.fieldName
|
||||||
|
tokens = t.getTokens()
|
||||||
|
case *filterExactPrefix:
|
||||||
|
fieldName = t.fieldName
|
||||||
|
tokens = t.getTokens()
|
||||||
|
case *filterPhrase:
|
||||||
|
fieldName = t.fieldName
|
||||||
|
tokens = t.getTokens()
|
||||||
|
case *filterPrefix:
|
||||||
|
fieldName = t.fieldName
|
||||||
|
tokens = t.getTokens()
|
||||||
|
case *filterRegexp:
|
||||||
|
fieldName = t.fieldName
|
||||||
|
tokens = t.getTokens()
|
||||||
|
case *filterSequence:
|
||||||
|
fieldName = t.fieldName
|
||||||
|
tokens = t.getTokens()
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldName = getCanonicalColumnName(fieldName)
|
||||||
|
byFieldFilters[fieldName]++
|
||||||
|
|
||||||
|
if len(tokens) > 0 {
|
||||||
|
if _, ok := m[fieldName]; !ok {
|
||||||
|
fieldNames = append(fieldNames, fieldName)
|
||||||
|
}
|
||||||
|
m[fieldName] = append(m[fieldName], tokens)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var byFieldTokens []fieldTokens
|
||||||
|
for _, fieldName := range fieldNames {
|
||||||
|
if byFieldFilters[fieldName] < 2 {
|
||||||
|
// It is faster to perform bloom filter match inline when visiting the corresponding column
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
commonTokens := getCommonTokens(m[fieldName])
|
||||||
|
if len(commonTokens) > 0 {
|
||||||
|
byFieldTokens = append(byFieldTokens, fieldTokens{
|
||||||
|
field: fieldName,
|
||||||
|
tokens: commonTokens,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fo.byFieldTokens = byFieldTokens
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue