Skip to content

Rewrite conditions on same attribute to equivalent array operation (2) - #6353

Merged
stoewer merged 30 commits into
grafana:mainfrom
stoewer:rewrite-or-in-queries-2
Feb 11, 2026
Merged

Rewrite conditions on same attribute to equivalent array operation (2)#6353
stoewer merged 30 commits into
grafana:mainfrom
stoewer:rewrite-or-in-queries-2

Conversation

@stoewer

@stoewer stoewer commented Jan 30, 2026

Copy link
Copy Markdown
Contributor

What this PR does:
Rewrite queries like { .a="a" || .a="b" } into the equivalent, faster form { .a IN ["a", "b"] }. This AST optimization is applied by default, but it can be disabled using the query hint skip_optimization=true.

I've added the new operators IN, NOT IN, MATCH ANY, MATCH NONE to the AST. However, they are not actually parseable in TraceQL.

Note: This PR was created from the changes in #5827. Since reviewers requested larger changes and rebasing caused lots of conflicts, I decided to create a new PR instead of updating the new one

Limitations

  • Does not optimize conditions with types that don't have directly corresponding array type such as: TypeKind, TypeStatus, TypeDuration
  • Does not optimize conditions not adjacent to each other like { .a="a" && .b="b" || .a="c" }
  • The syntax of the array form e.g. { .a IN ["a", "b"] } only works internally, the syntax is not actually available in TraceQL

Breaking Changes

  • For consistency and simplicity I've also changed the syntax of the array matching of != and `!~' slightly:
    • != now means NOT IN (previously: CONTAINS NOT EQUAL)
    • !~ now means MATCH NONE (previously: CONTAINS NON-MATCH)
  • Regex operands must be of type string or string array (previously, any value convertible to a valid regex was accepted)

Which issue(s) this PR fixes:
Fixes grafana/tempo-squad#874

Checklist

  • Tests updated
  • Documentation added
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]
Example ["aa", "bb"] -> [`aa`, `bb`]
The rewriter handles the following cases:
- { .a =  "a" || .a =  "b" } => { .a IN  ["a", "b"] }
- { .a != "a" && .a != "b" } => { .a NOT IN ["a", "b"] }
- { .a =~ "a" || .a =~ "b" } => { .a MATCH ANY ["a", "b"] }
- { .a !~ "a" && .a !~ "b" } => { .a MATCH NONE ["a", "b"] }
BinaryOperation.validate() considered everythin a valid regex where
FieldExpression.EncodeToString(false) happened to return a valid regex.
With this change the RHS of a regex operation is required to be a string
or string array
@stoewer

stoewer commented Jan 30, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown
@stoewer
stoewer marked this pull request as ready for review January 30, 2026 13:33
Comment thread tempodb/tempodb_search_test.go Outdated
Comment thread pkg/traceql/parse.go
Comment thread pkg/traceql/ast.go
@stoewer

stoewer commented Feb 4, 2026

Copy link
Copy Markdown
Contributor Author

I ran some benchmarks:

  • main: same benchmark on the main branch
  • skip: this PR but with skip_optimization hint
  • optimize: this PR with optimizations applied

The first 4 sub-benchmarks are just simple queries where nothing can be optimized

Results:

goos: linux
goarch: amd64
pkg: github.com/grafana/tempo/tempodb/encoding/vparquet5
cpu: AMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M       
                                                    │    main     │                skip                 │              optimize               │
                                                    │   sec/op    │   sec/op     vs base                │   sec/op     vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 251.9m ± 2%   255.0m ± 1%        ~ (p=0.105 n=10)   254.5m ± 2%        ~ (p=0.190 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               4.976m ± 2%   4.918m ± 3%        ~ (p=0.143 n=10)   5.097m ± 2%   +2.44% (p=0.029 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             234.2m ± 3%   236.3m ± 3%        ~ (p=0.739 n=10)   231.9m ± 2%        ~ (p=0.739 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           13.14m ± 2%   12.93m ± 2%   -1.56% (p=0.019 n=10)   13.15m ± 2%        ~ (p=0.971 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                616.5m ± 2%   611.5m ± 2%        ~ (p=0.089 n=10)   264.9m ± 4%  -57.03% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 621.2m ± 1%   615.4m ± 1%        ~ (p=0.218 n=10)   262.6m ± 2%  -57.73% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4             2.565 ± 1%    2.989 ± 1%  +16.54% (p=0.000 n=10)    2.816 ± 2%   +9.78% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                 1.728 ± 1%    1.878 ± 1%   +8.71% (p=0.000 n=10)    1.460 ± 2%  -15.51% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                  1.844 ± 1%    1.960 ± 3%   +6.30% (p=0.000 n=10)    1.686 ± 3%   -8.54% (p=0.002 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4             2.228 ± 1%    2.554 ± 1%  +14.62% (p=0.000 n=10)    2.071 ± 1%   -7.03% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       492.7m ± 3%   522.1m ± 3%   +5.96% (p=0.002 n=10)   250.3m ± 2%  -49.20% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        734.9m ± 2%   782.7m ± 1%   +6.50% (p=0.000 n=10)   565.5m ± 3%  -23.06% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4    2.566 ± 1%    2.909 ± 1%  +13.34% (p=0.000 n=10)    2.654 ± 2%   +3.42% (p=0.000 n=10)
geomean                                               442.6m        465.5m        +5.18%                  356.2m       -19.52%

                                                    │     main     │                 skip                 │               optimize                │
                                                    │     B/s      │     B/s       vs base                │     B/s       vs base                 │
BackendBlockTraceQL/spanAttValMatch-4                 321.8Mi ± 2%   317.9Mi ± 1%        ~ (p=0.105 n=10)   318.5Mi ± 2%         ~ (p=0.190 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               1.868Gi ± 2%   1.890Gi ± 3%        ~ (p=0.143 n=10)   1.822Gi ± 2%    -2.44% (p=0.029 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             346.4Mi ± 3%   343.3Mi ± 3%        ~ (p=0.739 n=10)   349.8Mi ± 2%         ~ (p=0.725 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           771.7Mi ± 2%   784.0Mi ± 2%   +1.59% (p=0.019 n=10)   771.0Mi ± 2%         ~ (p=0.971 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                133.0Mi ± 2%   134.1Mi ± 2%        ~ (p=0.089 n=10)   306.0Mi ± 4%  +130.07% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 132.0Mi ± 1%   133.3Mi ± 1%        ~ (p=0.218 n=10)   308.7Mi ± 2%  +133.89% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            31.60Mi ± 1%   27.12Mi ± 1%  -14.20% (p=0.000 n=10)   28.79Mi ± 2%    -8.92% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                58.57Mi ± 1%   53.88Mi ± 1%   -8.01% (p=0.000 n=10)   69.32Mi ± 2%   +18.36% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 54.89Mi ± 1%   51.64Mi ± 3%   -5.92% (p=0.000 n=10)   60.02Mi ± 2%    +9.34% (p=0.002 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            45.42Mi ± 1%   39.63Mi ± 1%  -12.77% (p=0.000 n=10)   48.86Mi ± 1%    +7.56% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       165.9Mi ± 3%   156.6Mi ± 3%   -5.62% (p=0.002 n=10)   325.1Mi ± 2%   +95.97% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        111.2Mi ± 2%   104.5Mi ± 1%   -6.10% (p=0.000 n=10)   143.9Mi ± 3%   +29.39% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   31.85Mi ± 1%   28.10Mi ± 1%  -11.77% (p=0.000 n=10)   30.67Mi ± 2%    -3.73% (p=0.000 n=10)
geomean                                               139.9Mi        133.0Mi        -4.92%                  173.3Mi        +23.91%

                                                    │    main    │                skip                 │              optimize               │
                                                    │  MB_io/op  │  MB_io/op   vs base                 │  MB_io/op   vs base                 │
BackendBlockTraceQL/spanAttValMatch-4                 85.00 ± 0%   85.00 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttValNoMatch-4               9.971 ± 0%   9.977 ± 0%       ~ (p=0.615 n=10)     9.972 ± 0%       ~ (p=1.000 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             85.06 ± 0%   85.06 ± 0%       ~ (p=1.000 n=10) ¹   85.06 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValNoMatch-4           10.63 ± 0%   10.63 ± 0%       ~ (p=1.000 n=10) ¹   10.63 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrEquals-4                85.98 ± 0%   85.98 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%  -1.14% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 85.98 ± 0%   85.98 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%  -1.14% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            85.00 ± 0%   85.00 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEquals-4                106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegex-4                 106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEquals-4            106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
geomean                                               64.90        64.90       +0.01%                    64.72       -0.28%
¹ all samples are equal

                                                    │     main      │                 skip                 │               optimize                │
                                                    │   spans/op    │  spans/op    vs base                 │  spans/op    vs base                  │
BackendBlockTraceQL/spanAttValMatch-4                 8.523k ± 0%     8.523k ± 0%       ~ (p=1.000 n=10) ¹   8.523k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttValNoMatch-4                0.000 ± 0%      0.000 ± 0%       ~ (p=1.000 n=10) ¹    0.000 ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValMatch-4             13.34k ± 0%     13.34k ± 0%       ~ (p=1.000 n=10) ¹   13.34k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValNoMatch-4            0.000 ± 0%      0.000 ± 0%       ~ (p=1.000 n=10) ¹    0.000 ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrEquals-4                8.692k ± 0%     8.692k ± 0%       ~ (p=1.000 n=10) ¹   8.692k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrRegex-4                 8.692k ± 0%     8.692k ± 0%       ~ (p=1.000 n=10) ¹   8.692k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrAndNotEquals-4            314.4k ± 0%     314.4k ± 0%       ~ (p=1.000 n=10) ¹   314.4k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEquals-4                215.7k ± 0%     215.7k ± 0%       ~ (p=1.000 n=10) ¹   223.5k ± 0%   +3.63% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 220.8k ± 0%     220.8k ± 0%       ~ (p=1.000 n=10) ¹   228.5k ± 0%   +3.49% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            127.7k ± 0%     127.7k ± 0%       ~ (p=1.000 n=10) ¹   140.6k ± 0%  +10.07% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       3.555k ± 0%     3.555k ± 0%       ~ (p=1.000 n=10) ¹   3.555k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        16.21k ± 0%     16.21k ± 0%       ~ (p=1.000 n=10) ¹   17.46k ± 0%   +7.71% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   314.4k ± 0%     314.4k ± 0%       ~ (p=1.000 n=10) ¹   314.4k ± 0%        ~ (p=1.000 n=10) ¹
geomean                                                           ²                +0.00%                ²                 +1.86%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                    │     main     │                skip                 │               optimize               │
                                                    │     B/op     │     B/op      vs base               │     B/op      vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 403.0Mi ± 0%   402.1Mi ± 1%       ~ (p=0.481 n=10)   402.9Mi ± 0%        ~ (p=0.971 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               5.198Mi ± 5%   5.289Mi ± 3%       ~ (p=0.481 n=10)   5.336Mi ± 5%        ~ (p=0.529 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             450.2Mi ± 0%   450.6Mi ± 1%       ~ (p=0.796 n=10)   450.3Mi ± 0%        ~ (p=0.393 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           13.92Mi ± 1%   13.91Mi ± 2%       ~ (p=0.912 n=10)   13.89Mi ± 1%        ~ (p=0.971 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                420.8Mi ± 2%   420.0Mi ± 1%       ~ (p=0.529 n=10)   403.9Mi ± 0%   -4.02% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 420.7Mi ± 1%   421.0Mi ± 1%       ~ (p=0.631 n=10)   403.8Mi ± 0%   -4.02% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            2.683Gi ± 1%   2.684Gi ± 0%       ~ (p=0.481 n=10)   2.674Gi ± 2%   -0.31% (p=0.029 n=10)
BackendBlockTraceQL/resourceOrEquals-4                1.125Gi ± 1%   1.127Gi ± 1%       ~ (p=0.684 n=10)   1.113Gi ± 1%   -1.00% (p=0.001 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 1.400Gi ± 3%   1.397Gi ± 3%       ~ (p=0.739 n=10)   1.389Gi ± 0%   -0.82% (p=0.023 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            2.119Gi ± 2%   2.085Gi ± 2%       ~ (p=0.218 n=10)   1.789Gi ± 2%  -15.55% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       424.0Mi ± 1%   423.8Mi ± 1%       ~ (p=0.912 n=10)   446.0Mi ± 1%   +5.18% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        830.8Mi ± 2%   830.0Mi ± 2%       ~ (p=0.631 n=10)   834.7Mi ± 2%   +0.48% (p=0.043 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   2.871Gi ± 1%   2.872Gi ± 1%       ~ (p=0.853 n=10)   2.513Gi ± 2%  -12.49% (p=0.000 n=10)
geomean                                               440.7Mi        440.7Mi       -0.02%                  429.8Mi        -2.48%

                                                    │    main     │                skip                │              optimize               │
                                                    │  allocs/op  │  allocs/op   vs base               │  allocs/op   vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 463.8k ± 0%   463.8k ± 0%       ~ (p=0.739 n=10)   463.8k ± 0%        ~ (p=0.853 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               40.10k ± 0%   40.10k ± 0%       ~ (p=0.906 n=10)   40.10k ± 0%   -0.01% (p=0.003 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             495.2k ± 0%   495.2k ± 0%       ~ (p=0.796 n=10)   495.2k ± 0%        ~ (p=0.239 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           40.22k ± 0%   40.22k ± 0%       ~ (p=0.428 n=10)   40.21k ± 0%   -0.01% (p=0.006 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                525.8k ± 1%   526.2k ± 1%       ~ (p=0.853 n=10)   468.9k ± 0%  -10.83% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 528.1k ± 1%   525.2k ± 1%       ~ (p=0.063 n=10)   469.2k ± 0%  -11.16% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            19.45M ± 0%   19.45M ± 0%       ~ (p=0.393 n=10)   19.42M ± 0%   -0.17% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                9.807M ± 0%   9.807M ± 0%       ~ (p=0.912 n=10)   9.427M ± 0%   -3.87% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 11.36M ± 0%   11.36M ± 0%       ~ (p=0.971 n=10)   10.99M ± 0%   -3.25% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            13.87M ± 0%   13.87M ± 0%       ~ (p=0.565 n=10)   11.86M ± 0%  -14.46% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       687.9k ± 0%   687.9k ± 0%       ~ (p=0.781 n=10)   682.4k ± 0%   -0.79% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        2.883M ± 0%   2.883M ± 0%       ~ (p=0.971 n=10)   2.873M ± 0%   -0.36% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   18.96M ± 0%   18.96M ± 0%       ~ (p=0.617 n=10)   18.96M ± 0%   -0.00% (p=0.000 n=10)
geomean                                               1.442M        1.441M       -0.04%                  1.390M        -3.59%
@stoewer

stoewer commented Feb 4, 2026

Copy link
Copy Markdown
Contributor Author

There are two things in the benchmark that I still need to look into:

  • why is skip slower than main?
  • why is spans/op larger for optimized? This could be a correctness issue
@stoewer

stoewer commented Feb 10, 2026

Copy link
Copy Markdown
Contributor Author

Here are the benchmark results after optimization and fixing the span/op bug. There are again 3 different benchmark runs with the following parameters:

  • main: same benchmark on the main branch
  • skip: this PR but with skip_optimization hint
  • optimize: this PR with optimizations applied

The first 4 sub-benchmarks are just simple queries where nothing can be optimized:

goos: linux
goarch: amd64
pkg: github.com/grafana/tempo/tempodb/encoding/vparquet5
cpu: AMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M       
                                                    │    main     │                skip                │              optimize               │
                                                    │   sec/op    │   sec/op     vs base               │   sec/op     vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 249.8m ± 1%   242.8m ± 5%  -2.83% (p=0.023 n=10)   242.6m ± 1%   -2.89% (p=0.000 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               4.741m ± 2%   4.730m ± 1%       ~ (p=0.796 n=10)   4.716m ± 2%        ~ (p=0.436 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             232.5m ± 2%   215.3m ± 1%  -7.42% (p=0.000 n=10)   213.9m ± 2%   -8.01% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           12.97m ± 1%   12.72m ± 1%  -1.92% (p=0.000 n=10)   12.66m ± 2%   -2.37% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                619.4m ± 1%   598.1m ± 2%  -3.43% (p=0.000 n=10)   257.3m ± 3%  -58.46% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 618.9m ± 2%   595.2m ± 2%  -3.83% (p=0.000 n=10)   249.9m ± 2%  -59.62% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4             2.578 ± 1%    2.643 ± 1%  +2.53% (p=0.000 n=10)    2.661 ± 3%   +3.22% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                 1.730 ± 2%    1.778 ± 1%  +2.73% (p=0.000 n=10)    1.423 ± 3%  -17.76% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                  1.867 ± 1%    1.863 ± 1%       ~ (p=0.739 n=10)    1.636 ± 2%  -12.36% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4             2.267 ± 2%    2.280 ± 2%  +0.57% (p=0.015 n=10)    1.963 ± 3%  -13.41% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       492.7m ± 1%   489.1m ± 2%  -0.74% (p=0.043 n=10)   231.9m ± 3%  -52.93% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        736.1m ± 1%   735.0m ± 3%       ~ (p=0.853 n=10)   544.6m ± 3%  -26.01% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4    2.580 ± 1%    2.627 ± 1%  +1.82% (p=0.000 n=10)    2.501 ± 1%   -3.06% (p=0.000 n=10)
geomean                                               441.5m        436.8m       -1.05%                  338.5m       -23.32%

                                                    │     main     │                skip                 │               optimize                │
                                                    │     B/s      │     B/s       vs base               │     B/s       vs base                 │
BackendBlockTraceQL/spanAttValMatch-4                 324.5Mi ± 1%   333.9Mi ± 5%  +2.92% (p=0.023 n=10)   334.1Mi ± 1%    +2.98% (p=0.000 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               1.960Gi ± 2%   1.963Gi ± 1%       ~ (p=0.796 n=10)   1.969Gi ± 2%         ~ (p=0.529 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             348.9Mi ± 2%   376.8Mi ± 1%  +8.02% (p=0.000 n=10)   379.2Mi ± 2%    +8.70% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           781.9Mi ± 1%   797.2Mi ± 1%  +1.96% (p=0.000 n=10)   800.9Mi ± 2%    +2.43% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                132.4Mi ± 1%   137.1Mi ± 2%  +3.56% (p=0.000 n=10)   315.0Mi ± 3%  +137.97% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 132.5Mi ± 2%   137.8Mi ± 2%  +3.98% (p=0.000 n=10)   324.3Mi ± 2%  +144.80% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            31.45Mi ± 1%   30.67Mi ± 1%  -2.47% (p=0.000 n=10)   30.47Mi ± 3%    -3.12% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                58.48Mi ± 2%   56.93Mi ± 1%  -2.65% (p=0.000 n=10)   71.12Mi ± 3%   +21.60% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 54.21Mi ± 1%   54.33Mi ± 1%       ~ (p=0.724 n=10)   61.86Mi ± 2%   +14.11% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            44.64Mi ± 2%   44.38Mi ± 2%  -0.59% (p=0.014 n=10)   51.55Mi ± 3%   +15.48% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       165.9Mi ± 1%   167.2Mi ± 2%  +0.74% (p=0.043 n=10)   351.0Mi ± 3%  +111.52% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        111.1Mi ± 1%   111.2Mi ± 3%       ~ (p=0.853 n=10)   149.5Mi ± 3%   +34.55% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   31.69Mi ± 1%   31.13Mi ± 1%  -1.78% (p=0.000 n=10)   32.54Mi ± 1%    +2.69% (p=0.000 n=10)
geomean                                               140.2Mi        141.7Mi       +1.05%                  182.4Mi        +30.05%

                                                    │    main    │                skip                 │              optimize               │
                                                    │  MB_io/op  │  MB_io/op   vs base                 │  MB_io/op   vs base                 │
BackendBlockTraceQL/spanAttValMatch-4                 85.00 ± 0%   85.00 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttValNoMatch-4               9.971 ± 0%   9.971 ± 0%       ~ (p=0.198 n=10)     9.971 ± 0%       ~ (p=0.507 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             85.06 ± 0%   85.06 ± 0%       ~ (p=1.000 n=10) ¹   85.06 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValNoMatch-4           10.63 ± 0%   10.63 ± 0%       ~ (p=1.000 n=10) ¹   10.63 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrEquals-4                85.98 ± 0%   85.98 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%  -1.14% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 85.98 ± 0%   85.98 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%  -1.14% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            85.00 ± 0%   85.00 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEquals-4                106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegex-4                 106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEquals-4            106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
geomean                                               64.90        64.90       +0.00%                    64.72       -0.28%
¹ all samples are equal

                                                    │      main      │                 skip                  │               optimize                │
                                                    │    spans/op    │  spans/op    vs base                  │  spans/op    vs base                  │
BackendBlockTraceQL/spanAttValMatch-4                  8.523k ± 0%     8.523k ± 0%        ~ (p=1.000 n=10) ¹   8.523k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttValNoMatch-4                 0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹    0.000 ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValMatch-4             13.340k ± 0%     9.406k ± 0%  -29.49% (p=0.000 n=10)     9.406k ± 0%  -29.49% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4             0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹    0.000 ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrEquals-4                 8.692k ± 0%     8.692k ± 0%        ~ (p=1.000 n=10) ¹   8.692k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrRegex-4                  8.692k ± 0%     8.692k ± 0%        ~ (p=1.000 n=10) ¹   8.692k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrAndNotEquals-4             314.4k ± 0%     314.4k ± 0%        ~ (p=1.000 n=10) ¹   314.4k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEquals-4                 215.7k ± 0%     215.7k ± 0%        ~ (p=1.000 n=10) ¹   215.7k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegex-4                  220.8k ± 0%     220.8k ± 0%        ~ (p=1.000 n=10) ¹   220.8k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEquals-4             127.7k ± 0%     127.7k ± 0%   -0.00% (p=0.000 n=10)     127.7k ± 0%   -0.00% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4        3.555k ± 0%     3.555k ± 0%        ~ (p=1.000 n=10) ¹   3.555k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegexIntrinsic-4         16.21k ± 0%     16.21k ± 0%        ~ (p=1.000 n=10) ¹   16.21k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4    314.4k ± 0%     314.4k ± 0%        ~ (p=1.000 n=10) ¹   314.4k ± 0%        ~ (p=1.000 n=10) ¹
geomean                                                            ²                 -2.65%                ²                 -2.65%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                    │     main     │                skip                 │               optimize               │
                                                    │     B/op     │     B/op      vs base               │     B/op      vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 401.5Mi ± 1%   401.4Mi ± 0%       ~ (p=0.481 n=10)   402.6Mi ± 0%        ~ (p=0.105 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               5.257Mi ± 3%   5.269Mi ± 5%       ~ (p=0.796 n=10)   5.158Mi ± 4%        ~ (p=0.481 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             449.9Mi ± 0%   443.5Mi ± 0%  -1.43% (p=0.000 n=10)   442.7Mi ± 0%   -1.60% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           13.82Mi ± 2%   13.86Mi ± 2%       ~ (p=0.631 n=10)   13.96Mi ± 2%        ~ (p=0.631 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                421.5Mi ± 1%   422.5Mi ± 2%       ~ (p=0.971 n=10)   403.0Mi ± 0%   -4.39% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 421.6Mi ± 1%   417.7Mi ± 1%       ~ (p=0.075 n=10)   403.6Mi ± 0%   -4.26% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            2.686Gi ± 2%   2.682Gi ± 2%       ~ (p=0.315 n=10)   2.674Gi ± 0%   -0.44% (p=0.015 n=10)
BackendBlockTraceQL/resourceOrEquals-4                1.127Gi ± 0%   1.127Gi ± 1%       ~ (p=0.853 n=10)   1.100Gi ± 1%   -2.39% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 1.402Gi ± 3%   1.401Gi ± 3%       ~ (p=0.529 n=10)   1.374Gi ± 3%   -2.00% (p=0.005 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            2.120Gi ± 2%   2.121Gi ± 2%       ~ (p=0.631 n=10)   1.767Gi ± 2%  -16.66% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       421.2Mi ± 3%   422.2Mi ± 1%       ~ (p=0.353 n=10)   443.6Mi ± 0%   +5.31% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        829.2Mi ± 2%   830.3Mi ± 2%       ~ (p=0.481 n=10)   830.4Mi ± 2%        ~ (p=0.436 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   2.871Gi ± 0%   2.873Gi ± 1%       ~ (p=0.739 n=10)   2.515Gi ± 0%  -12.40% (p=0.000 n=10)
geomean                                               440.7Mi        440.3Mi       -0.10%                  426.7Mi        -3.18%

                                                    │    main     │                skip                │              optimize               │
                                                    │  allocs/op  │  allocs/op   vs base               │  allocs/op   vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 463.8k ± 0%   463.8k ± 0%       ~ (p=0.315 n=10)   463.8k ± 0%        ~ (p=0.529 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               40.10k ± 0%   40.10k ± 0%       ~ (p=0.994 n=10)   40.10k ± 0%   -0.01% (p=0.005 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             495.2k ± 0%   450.3k ± 0%  -9.06% (p=0.000 n=10)   450.3k ± 0%   -9.07% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           40.22k ± 0%   40.22k ± 0%       ~ (p=0.395 n=10)   40.21k ± 0%        ~ (p=0.078 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                525.4k ± 1%   525.5k ± 1%       ~ (p=0.912 n=10)   468.9k ± 0%  -10.76% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 522.4k ± 1%   527.2k ± 1%       ~ (p=0.089 n=10)   469.2k ± 0%  -10.18% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            19.45M ± 0%   19.45M ± 0%       ~ (p=0.615 n=10)   19.42M ± 0%   -0.17% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                9.807M ± 0%   9.807M ± 0%       ~ (p=0.393 n=10)   9.418M ± 0%   -3.96% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 11.36M ± 0%   11.36M ± 0%       ~ (p=0.869 n=10)   10.98M ± 0%   -3.32% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            13.87M ± 0%   13.87M ± 0%       ~ (p=0.927 n=10)   11.78M ± 0%  -15.05% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       687.8k ± 0%   687.9k ± 0%       ~ (p=0.075 n=10)   689.5k ± 0%   +0.25% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        2.883M ± 0%   2.883M ± 0%       ~ (p=0.271 n=10)   2.883M ± 0%   -0.01% (p=0.001 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   18.96M ± 0%   18.96M ± 0%       ~ (p=0.912 n=10)   18.96M ± 0%   -0.00% (p=0.000 n=10)
geomean                                               1.440M        1.431M       -0.66%                  1.380M        -4.17%
@stoewer

stoewer commented Feb 10, 2026

Copy link
Copy Markdown
Contributor Author

Commit bc3b95b fixes a bug that was introduced with the virtual row numbers PR #5943. This is what caused the additional span/op in the first benchmark.
Since this bug is already in main we see now less span/op in the benchmarks skip and optimize:

BackendBlockTraceQL/resourceAttValMatch-4             13.340k ± 0%     9.406k ± 0%  -29.49% (p=0.000 n=10)     9.406k ± 0%  -29.49% (p=0.000 n=10)
stoewer and others added 3 commits February 10, 2026 14:08

@mdisibio mdisibio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm after latest changes, thanks. Discussed offline and we want to dig into the virtual row number fix a little more before merging.

This helps avoid additional spans/op in queries with only
resource attributes
@stoewer

stoewer commented Feb 11, 2026

Copy link
Copy Markdown
Contributor Author

Latest benchmark results with the new fix for the additional spans/op:

goos: linux
goarch: amd64
pkg: github.com/grafana/tempo/tempodb/encoding/vparquet5
cpu: AMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M       
                                                    │    main     │                skip                │              optimize               │
                                                    │   sec/op    │   sec/op     vs base               │   sec/op     vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 250.5m ± 1%   239.6m ± 2%  -4.34% (p=0.000 n=10)   242.6m ± 4%   -3.18% (p=0.005 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               4.892m ± 2%   4.741m ± 1%  -3.08% (p=0.000 n=10)   4.699m ± 2%   -3.95% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             231.5m ± 2%   213.2m ± 3%  -7.90% (p=0.000 n=10)   213.9m ± 2%   -7.60% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           12.39m ± 2%   12.25m ± 1%  -1.14% (p=0.011 n=10)   12.28m ± 1%   -0.86% (p=0.005 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                594.9m ± 3%   606.0m ± 2%       ~ (p=0.089 n=10)   248.6m ± 2%  -58.22% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 589.2m ± 3%   598.9m ± 2%       ~ (p=0.353 n=10)   249.8m ± 2%  -57.60% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4             2.510 ± 2%    2.631 ± 1%  +4.79% (p=0.000 n=10)    2.627 ± 2%   +4.67% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                 1.683 ± 2%    1.743 ± 1%  +3.54% (p=0.000 n=10)    1.384 ± 1%  -17.76% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                  1.815 ± 1%    1.848 ± 2%  +1.80% (p=0.019 n=10)    1.599 ± 2%  -11.92% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4             2.185 ± 1%    2.269 ± 1%  +3.81% (p=0.000 n=10)    1.905 ± 2%  -12.84% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       477.6m ± 2%   483.1m ± 2%       ~ (p=0.143 n=10)   226.8m ± 2%  -52.51% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        708.9m ± 1%   721.5m ± 2%  +1.78% (p=0.007 n=10)   527.1m ± 2%  -25.64% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4    2.494 ± 1%    2.584 ± 1%  +3.59% (p=0.000 n=10)    2.452 ± 1%   -1.70% (p=0.000 n=10)
geomean                                               430.5m        432.7m       +0.51%                  332.4m       -22.79%

                                                    │     main     │                skip                 │               optimize                │
                                                    │     B/s      │     B/s       vs base               │     B/s       vs base                 │
BackendBlockTraceQL/spanAttValMatch-4                 323.6Mi ± 1%   338.3Mi ± 2%  +4.54% (p=0.000 n=10)   334.2Mi ± 4%    +3.28% (p=0.005 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               1.899Gi ± 2%   1.959Gi ± 1%  +3.16% (p=0.000 n=10)   1.978Gi ± 2%    +4.14% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             350.4Mi ± 2%   380.4Mi ± 3%  +8.57% (p=0.000 n=10)   379.2Mi ± 2%    +8.23% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           818.5Mi ± 2%   827.9Mi ± 1%  +1.16% (p=0.011 n=10)   825.6Mi ± 1%    +0.87% (p=0.005 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                137.8Mi ± 3%   135.3Mi ± 2%       ~ (p=0.079 n=10)   326.1Mi ± 2%  +136.60% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 139.2Mi ± 3%   136.9Mi ± 2%       ~ (p=0.342 n=10)   324.5Mi ± 2%  +133.15% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            32.29Mi ± 2%   30.82Mi ± 1%  -4.56% (p=0.000 n=10)   30.86Mi ± 2%    -4.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                60.13Mi ± 2%   58.07Mi ± 1%  -3.42% (p=0.000 n=10)   73.11Mi ± 1%   +21.59% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 55.74Mi ± 1%   54.76Mi ± 2%  -1.77% (p=0.018 n=10)   63.29Mi ± 2%   +13.54% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            46.31Mi ± 1%   44.61Mi ± 1%  -3.66% (p=0.000 n=10)   53.13Mi ± 2%   +14.74% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       171.2Mi ± 2%   169.2Mi ± 2%       ~ (p=0.143 n=10)   358.9Mi ± 2%  +109.62% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        115.3Mi ± 1%   113.3Mi ± 2%  -1.75% (p=0.007 n=10)   154.4Mi ± 2%   +33.89% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   32.78Mi ± 1%   31.64Mi ± 1%  -3.46% (p=0.000 n=10)   33.20Mi ± 1%    +1.29% (p=0.004 n=10)
geomean                                               143.8Mi        143.1Mi       -0.51%                  185.7Mi        +29.17%

                                                    │    main    │                skip                 │              optimize               │
                                                    │  MB_io/op  │  MB_io/op   vs base                 │  MB_io/op   vs base                 │
BackendBlockTraceQL/spanAttValMatch-4                 85.00 ± 0%   85.00 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttValNoMatch-4               9.971 ± 0%   9.969 ± 0%       ~ (p=0.580 n=10)     9.975 ± 0%       ~ (p=0.648 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             85.06 ± 0%   85.06 ± 0%       ~ (p=1.000 n=10) ¹   85.06 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValNoMatch-4           10.63 ± 0%   10.63 ± 0%       ~ (p=1.000 n=10) ¹   10.63 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrEquals-4                85.98 ± 0%   85.98 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%  -1.14% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 85.98 ± 0%   85.98 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%  -1.14% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            85.00 ± 0%   85.00 ± 0%       ~ (p=1.000 n=10) ¹   85.00 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEquals-4                106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegex-4                 106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEquals-4            106.1 ± 0%   106.1 ± 0%       ~ (p=1.000 n=10) ¹   106.1 ± 0%       ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   85.73 ± 0%   85.73 ± 0%       ~ (p=1.000 n=10) ¹   85.35 ± 0%  -0.44% (p=0.000 n=10)
geomean                                               64.90        64.90       -0.00%                    64.72       -0.28%
¹ all samples are equal

                                                    │      main      │                 skip                  │               optimize                │
                                                    │    spans/op    │  spans/op    vs base                  │  spans/op    vs base                  │
BackendBlockTraceQL/spanAttValMatch-4                  8.523k ± 0%     8.523k ± 0%        ~ (p=1.000 n=10) ¹   8.523k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttValNoMatch-4                 0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹    0.000 ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAttValMatch-4             13.340k ± 0%     9.406k ± 0%  -29.49% (p=0.000 n=10)     9.406k ± 0%  -29.49% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4             0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹    0.000 ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrEquals-4                 8.692k ± 0%     8.692k ± 0%        ~ (p=1.000 n=10) ¹   8.692k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrOrRegex-4                  8.692k ± 0%     8.692k ± 0%        ~ (p=1.000 n=10) ¹   8.692k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/spanAttrAndNotEquals-4             314.4k ± 0%     314.4k ± 0%        ~ (p=1.000 n=10) ¹   314.4k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrEquals-4                 215.7k ± 0%     215.7k ± 0%        ~ (p=1.000 n=10) ¹   215.7k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegex-4                  220.8k ± 0%     220.8k ± 0%        ~ (p=1.000 n=10) ¹   220.8k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEquals-4             127.7k ± 0%     127.7k ± 0%   -0.00% (p=0.000 n=10)     127.7k ± 0%   -0.00% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4        3.555k ± 0%     3.555k ± 0%        ~ (p=1.000 n=10) ¹   3.555k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceOrRegexIntrinsic-4         16.21k ± 0%     16.21k ± 0%        ~ (p=1.000 n=10) ¹   16.21k ± 0%        ~ (p=1.000 n=10) ¹
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4    314.4k ± 0%     314.4k ± 0%        ~ (p=1.000 n=10) ¹   314.4k ± 0%        ~ (p=1.000 n=10) ¹
geomean                                                            ²                 -2.65%                ²                 -2.65%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                    │     main     │                skip                 │               optimize               │
                                                    │     B/op     │     B/op      vs base               │     B/op      vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 403.3Mi ± 0%   403.1Mi ± 0%       ~ (p=0.912 n=10)   402.6Mi ± 1%        ~ (p=0.631 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               5.366Mi ± 5%   5.269Mi ± 3%       ~ (p=0.247 n=10)   5.390Mi ± 6%        ~ (p=0.796 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             450.1Mi ± 1%   443.0Mi ± 0%  -1.60% (p=0.000 n=10)   443.2Mi ± 0%   -1.54% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           13.92Mi ± 1%   13.95Mi ± 1%       ~ (p=0.971 n=10)   14.06Mi ± 2%        ~ (p=0.315 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                419.8Mi ± 2%   422.7Mi ± 1%       ~ (p=0.393 n=10)   402.6Mi ± 1%   -4.09% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 421.0Mi ± 2%   421.8Mi ± 2%       ~ (p=0.796 n=10)   402.9Mi ± 0%   -4.31% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            2.661Gi ± 1%   2.685Gi ± 2%       ~ (p=0.218 n=10)   2.675Gi ± 0%        ~ (p=0.853 n=10)
BackendBlockTraceQL/resourceOrEquals-4                1.126Gi ± 0%   1.127Gi ± 1%       ~ (p=0.739 n=10)   1.091Gi ± 1%   -3.12% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 1.400Gi ± 3%   1.404Gi ± 0%  +0.32% (p=0.009 n=10)   1.376Gi ± 3%   -1.69% (p=0.003 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            2.122Gi ± 0%   2.123Gi ± 0%       ~ (p=0.971 n=10)   1.767Gi ± 2%  -16.75% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       420.7Mi ± 1%   421.7Mi ± 4%       ~ (p=0.912 n=10)   444.6Mi ± 0%   +5.68% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        829.2Mi ± 2%   829.2Mi ± 2%       ~ (p=0.481 n=10)   830.7Mi ± 0%        ~ (p=0.247 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   2.873Gi ± 0%   2.872Gi ± 1%       ~ (p=0.529 n=10)   2.514Gi ± 2%  -12.51% (p=0.000 n=10)
geomean                                               441.3Mi        441.0Mi       -0.07%                  428.2Mi        -2.97%

                                                    │    main     │                skip                │              optimize               │
                                                    │  allocs/op  │  allocs/op   vs base               │  allocs/op   vs base                │
BackendBlockTraceQL/spanAttValMatch-4                 463.8k ± 0%   463.8k ± 0%       ~ (p=0.072 n=10)   463.8k ± 0%        ~ (p=0.566 n=10)
BackendBlockTraceQL/spanAttValNoMatch-4               40.08k ± 0%   40.10k ± 0%  +0.05% (p=0.000 n=10)   40.10k ± 0%   +0.05% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValMatch-4             495.2k ± 0%   450.3k ± 0%  -9.06% (p=0.000 n=10)   450.3k ± 0%   -9.06% (p=0.000 n=10)
BackendBlockTraceQL/resourceAttValNoMatch-4           40.19k ± 0%   40.22k ± 0%  +0.06% (p=0.000 n=10)   40.22k ± 0%   +0.06% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrEquals-4                525.6k ± 1%   526.2k ± 0%       ~ (p=0.853 n=10)   468.8k ± 0%  -10.80% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrOrRegex-4                 526.0k ± 1%   525.7k ± 1%       ~ (p=1.000 n=10)   469.2k ± 0%  -10.80% (p=0.000 n=10)
BackendBlockTraceQL/spanAttrAndNotEquals-4            19.45M ± 0%   19.45M ± 0%       ~ (p=0.280 n=10)   19.42M ± 0%   -0.17% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEquals-4                9.807M ± 0%   9.807M ± 0%       ~ (p=0.869 n=10)   9.418M ± 0%   -3.97% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegex-4                 11.36M ± 0%   11.36M ± 0%  +0.00% (p=0.003 n=10)   10.98M ± 0%   -3.32% (p=0.000 n=10)
BackendBlockTraceQL/resourceAndNotEquals-4            13.87M ± 0%   13.87M ± 0%       ~ (p=0.123 n=10)   11.78M ± 0%  -15.05% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrEqualsIntrinsic-4       687.7k ± 0%   687.7k ± 0%       ~ (p=0.631 n=10)   689.5k ± 0%   +0.26% (p=0.000 n=10)
BackendBlockTraceQL/resourceOrRegexIntrinsic-4        2.883M ± 0%   2.883M ± 0%       ~ (p=0.739 n=10)   2.883M ± 0%   -0.01% (p=0.002 n=10)
BackendBlockTraceQL/resourceAndNotEqualsIntrinsic-4   18.96M ± 0%   18.96M ± 0%       ~ (p=0.529 n=10)   18.96M ± 0%   -0.00% (p=0.000 n=10)
geomean                                               1.441M        1.431M       -0.71%                  1.380M        -4.21%

stoewer added a commit to stoewer/tempo that referenced this pull request Feb 11, 2026
This helps avoid additional spans/op in queries with only
resource attributes

This change part of grafana#6353
stoewer added a commit to stoewer/tempo that referenced this pull request Feb 11, 2026
This helps avoid additional spans/op in queries with only
resource attributes

This fix was part of grafana#6353
@stoewer
stoewer merged commit af65f59 into grafana:main Feb 11, 2026
23 checks passed
stoewer added a commit that referenced this pull request Feb 11, 2026
* Read to first virtual row after seeking on a low definition level

This helps avoid additional spans/op in queries with only
resource attributes

This fix was part of #6353

* CHANGELOG.md
@stoewer
stoewer deleted the rewrite-or-in-queries-2 branch February 12, 2026 09:51
mattdurham pushed a commit to mattdurham/tempo that referenced this pull request Jun 18, 2026
…rafana#6353)

* Add operators IN, NOT IN, MATCH ANY, and MATCH NONE

* Implement Static.append()

* Print string arrays with '`' instead of '"'

Example ["aa", "bb"] -> [`aa`, `bb`]

* Rewrite binary operations to array equivalent

The rewriter handles the following cases:
- { .a =  "a" || .a =  "b" } => { .a IN  ["a", "b"] }
- { .a != "a" && .a != "b" } => { .a NOT IN ["a", "b"] }
- { .a =~ "a" || .a =~ "b" } => { .a MATCH ANY ["a", "b"] }
- { .a !~ "a" && .a !~ "b" } => { .a MATCH NONE ["a", "b"] }

* Add test cases with arrays to TestBinOp

* traceql.Parse() applies AST optimizations by default

* Rename predicate_test.go to predicates_test.go

* Add array predicates to parquetquery

* BREAKING CHANGE: more precise regex validation

BinaryOperation.validate() considered everythin a valid regex where
FieldExpression.EncodeToString(false) happened to return a valid regex.
With this change the RHS of a regex operation is required to be a string
or string array

* vp4: handle predicates with arrays correctly

* vp5: handle predicates with arrays correctly

* vp3: handle predicates with arrays correctly

* Add test cases for optimized queries

* Update query test examples with optimizable queries

* vp3: fix handling of array types

* CHANGELOG.md

* Pass array operators down to fetch layer

* Read to first virtual row after seeking on a low definition level

This helps avoid additional spans/op in queries with only
resource attributes

---------

Co-authored-by: Martin Disibio <mdisibio@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants