mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
app/vmselect/promql: add missing label filters to binary operands before query execution
This implements the optimization described at https://utcc.utoronto.ca/~cks/space/blog/sysadmin/PrometheusLabelNonOptimization See also https://github.com/cortexproject/cortex/issues/3253
This commit is contained in:
parent
5ef71974fe
commit
e9f2e2cbc9
5 changed files with 88 additions and 4 deletions
|
@ -175,6 +175,7 @@ func parsePromQLWithCache(q string) (metricsql.Expr, error) {
|
|||
if pcv == nil {
|
||||
e, err := metricsql.Parse(q)
|
||||
if err == nil {
|
||||
e = metricsql.Optimize(e)
|
||||
e = adjustCmpOps(e)
|
||||
}
|
||||
pcv = &parseCacheValue{
|
||||
|
|
2
go.mod
2
go.mod
|
@ -9,7 +9,7 @@ require (
|
|||
// like https://github.com/valyala/fasthttp/commit/996610f021ff45fdc98c2ce7884d5fa4e7f9199b
|
||||
github.com/VictoriaMetrics/fasthttp v1.0.7
|
||||
github.com/VictoriaMetrics/metrics v1.12.3
|
||||
github.com/VictoriaMetrics/metricsql v0.6.0
|
||||
github.com/VictoriaMetrics/metricsql v0.7.0
|
||||
github.com/aws/aws-sdk-go v1.35.3
|
||||
github.com/cespare/xxhash/v2 v2.1.1
|
||||
github.com/golang/snappy v0.0.2
|
||||
|
|
4
go.sum
4
go.sum
|
@ -61,8 +61,8 @@ github.com/VictoriaMetrics/metrics v1.12.2 h1:SG8iAmqavDNuh7GIdHPoGHUhDL23KeKfvS
|
|||
github.com/VictoriaMetrics/metrics v1.12.2/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE=
|
||||
github.com/VictoriaMetrics/metrics v1.12.3 h1:Fe6JHC6MSEKa+BtLhPN8WIvS+HKPzMc2evEpNeCGy7I=
|
||||
github.com/VictoriaMetrics/metrics v1.12.3/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE=
|
||||
github.com/VictoriaMetrics/metricsql v0.6.0 h1:JnHUmifuA3fdy1GQrmkZJFO+CwFrhLxKwzMv89wNgJ4=
|
||||
github.com/VictoriaMetrics/metricsql v0.6.0/go.mod h1:ylO7YITho/Iw6P71oEaGyHbO94bGoGtzWfLGqFhMIg8=
|
||||
github.com/VictoriaMetrics/metricsql v0.7.0 h1:YR/OvbsCH0dwUuc3r5GayTcuTdgWHJZo+4bqbaGl7WM=
|
||||
github.com/VictoriaMetrics/metricsql v0.7.0/go.mod h1:ylO7YITho/Iw6P71oEaGyHbO94bGoGtzWfLGqFhMIg8=
|
||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
|
|
83
vendor/github.com/VictoriaMetrics/metricsql/optimizer.go
generated
vendored
Normal file
83
vendor/github.com/VictoriaMetrics/metricsql/optimizer.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
package metricsql
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Optimize optimizes e in order to improve its performance.
|
||||
func Optimize(e Expr) Expr {
|
||||
switch t := e.(type) {
|
||||
case *BinaryOpExpr:
|
||||
// Convert `foo{filters1} op bar{filters2}` to `foo{filters1, filters2} op bar{filters1, filters2}`.
|
||||
// This should reduce the number of operations
|
||||
// See https://utcc.utoronto.ca/~cks/space/blog/sysadmin/PrometheusLabelNonOptimization
|
||||
// for details.
|
||||
switch t.Op {
|
||||
case "+", "-", "*", "/", "%", "^",
|
||||
"==", "!=", ">", "<", ">=", "<=",
|
||||
"if", "ifnot", "default":
|
||||
// The optimization can be applied only to these operations.
|
||||
default:
|
||||
return optimizeBinaryOpArgs(t)
|
||||
}
|
||||
if t.JoinModifier.Op != "" {
|
||||
return optimizeBinaryOpArgs(t)
|
||||
}
|
||||
if t.GroupModifier.Op != "" {
|
||||
return optimizeBinaryOpArgs(t)
|
||||
}
|
||||
meLeft, ok := t.Left.(*MetricExpr)
|
||||
if !ok || !meLeft.hasNonEmptyMetricGroup() {
|
||||
return optimizeBinaryOpArgs(t)
|
||||
}
|
||||
meRight, ok := t.Right.(*MetricExpr)
|
||||
if !ok || !meRight.hasNonEmptyMetricGroup() {
|
||||
return optimizeBinaryOpArgs(t)
|
||||
}
|
||||
lfs := intersectLabelFilters(meLeft.LabelFilters[1:], meRight.LabelFilters[1:])
|
||||
meLeft.LabelFilters = append(meLeft.LabelFilters[:1], lfs...)
|
||||
meRight.LabelFilters = append(meRight.LabelFilters[:1], lfs...)
|
||||
return t
|
||||
case *FuncExpr:
|
||||
for i := range t.Args {
|
||||
t.Args[i] = Optimize(t.Args[i])
|
||||
}
|
||||
return t
|
||||
case *AggrFuncExpr:
|
||||
for i := range t.Args {
|
||||
t.Args[i] = Optimize(t.Args[i])
|
||||
}
|
||||
return t
|
||||
default:
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
func optimizeBinaryOpArgs(be *BinaryOpExpr) *BinaryOpExpr {
|
||||
be.Left = Optimize(be.Left)
|
||||
be.Right = Optimize(be.Right)
|
||||
return be
|
||||
}
|
||||
|
||||
func intersectLabelFilters(a, b []LabelFilter) []LabelFilter {
|
||||
m := make(map[string]LabelFilter, len(a)+len(b))
|
||||
var buf []byte
|
||||
for _, lf := range a {
|
||||
buf = lf.AppendString(buf[:0])
|
||||
m[string(buf)] = lf
|
||||
}
|
||||
for _, lf := range b {
|
||||
buf = lf.AppendString(buf[:0])
|
||||
m[string(buf)] = lf
|
||||
}
|
||||
ss := make([]string, 0, len(m))
|
||||
for s := range m {
|
||||
ss = append(ss, s)
|
||||
}
|
||||
sort.Strings(ss)
|
||||
lfs := make([]LabelFilter, 0, len(ss))
|
||||
for _, s := range ss {
|
||||
lfs = append(lfs, m[s])
|
||||
}
|
||||
return lfs
|
||||
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -16,7 +16,7 @@ github.com/VictoriaMetrics/fasthttp/fasthttputil
|
|||
github.com/VictoriaMetrics/fasthttp/stackless
|
||||
# github.com/VictoriaMetrics/metrics v1.12.3
|
||||
github.com/VictoriaMetrics/metrics
|
||||
# github.com/VictoriaMetrics/metricsql v0.6.0
|
||||
# github.com/VictoriaMetrics/metricsql v0.7.0
|
||||
github.com/VictoriaMetrics/metricsql
|
||||
github.com/VictoriaMetrics/metricsql/binaryop
|
||||
# github.com/aws/aws-sdk-go v1.35.3
|
||||
|
|
Loading…
Reference in a new issue