Skip to content

MQE: subset selector elimination#14377

Open
charleskorn wants to merge 58 commits intomainfrom
charleskorn/subset-selector-elimination
Open

MQE: subset selector elimination#14377
charleskorn wants to merge 58 commits intomainfrom
charleskorn/subset-selector-elimination

Conversation

@charleskorn
Copy link
Contributor

@charleskorn charleskorn commented Feb 16, 2026

What this PR does

This PR adds support for subset selector elimination (SSE) in MQE, building on common subexpression elimination (CSE).

Where CSE eliminates repeated expressions like a in a / (a + b), SSE avoids reevaluating expressions that are a subset of another expression, such as request_count{status="success"} in request_count{status="success"} / request_count.

It also attempts to push down operations that can still be correctly applied before any subset filter is applied. For example, in rate(request_count{status="success"}[5m]) / rate(request_count[5m]), applying the status="success" filter to series and then calculating the rate produces the same result as calculating the rate on all series and then applying the filter - so the optimization pass tries to identify opportunities to apply the filtering as late as possible, to avoid duplicate work.

This improves query performance and reduces querier resource consumption, and reduces the load on store-gateways and ingesters, reducing their resource consumption.

This is a large PR. There are four main areas of change:

  • Planning changes:
    • The CSE optimization pass now handles both CSE and SSE, emitting the newly-introduced DuplicateFilter nodes to filter the result of a Duplicate node based on the provided matchers: pkg/streamingpromql/optimize/plan/commonsubexpressionelimination/optimization_pass.go
    • The multi-aggregation optimization pass now identifies aggregations where the input is the subset of another similar aggregation (eg. sum(foo{status="success"}) / sum(foo)), based on the output from the CSE / SSE optimization pass. This allows this common kind of query to avoid buffering anything: pkg/streamingpromql/optimize/plan/multiaggregation/optimization_pass.go
  • Evaluation changes:
    • Corresponding changes to the instant vector and range vector CSE operators: pkg/streamingpromql/optimize/plan/commonsubexpressionelimination/instant_vector_operator.go, range_vector_operator.go and series_data_ring_buffer.go
    • Corresponding changes to the multi-aggregation operator: pkg/streamingpromql/optimize/plan/multiaggregation/operator.go

Our benchmarks show no measurable impact to queries eligible to CSE despite the changes in this PR, and queries eligible for SSE show substantial improvement in latency (30-40% for non-trivial cases) with no increase in peak memory consumption.

There is one exception: the cases where the selector retrieves a single series. In these cases, the query evaluates significantly faster but has nearly 2x the peak memory consumption as before. I believe this is due to the fact that the queries finish very quickly and don't read the full response from ingester, so the gRPC stream is drained and closed asynchronously. This can overlap with the next iteration of the benchmark and therefore the next request to the ingester, causing the increased memory consumption that we see.

Benchmark results

goos: darwin
goarch: arm64
pkg: github.com/grafana/mimir/pkg/streamingpromql/benchmarks
cpu: Apple M1 Pro
                                                                                                                 │  before.txt  │              after.txt              │
                                                                                                                 │    sec/op    │    sec/op     vs base               │
Query/a_1{l=~"[13579].*"}_/_a_1,_instant_query/engine=Mimir-10                                                      561.3µ ± 3%   165.2µ ±  3%  -70.56% (p=0.002 n=6)
Query/a_1{l=~"[13579].*"}_/_a_1,_range_query_with_100_steps/engine=Mimir-10                                         551.7µ ± 2%   163.2µ ±  1%  -70.43% (p=0.002 n=6)
Query/a_1{l=~"[13579].*"}_/_a_1,_range_query_with_1000_steps/engine=Mimir-10                                        900.8µ ± 2%   179.0µ ±  1%  -80.13% (p=0.002 n=6)
Query/a_100{l=~"[13579].*"}_/_a_100,_instant_query/engine=Mimir-10                                                 1685.5µ ± 2%   807.4µ ±  1%  -52.10% (p=0.002 n=6)
Query/a_100{l=~"[13579].*"}_/_a_100,_range_query_with_100_steps/engine=Mimir-10                                     2.547m ± 2%   1.382m ±  0%  -45.75% (p=0.002 n=6)
Query/a_100{l=~"[13579].*"}_/_a_100,_range_query_with_1000_steps/engine=Mimir-10                                    9.596m ± 3%   5.970m ±  6%  -37.79% (p=0.002 n=6)
Query/a_2000{l=~"[13579].*"}_/_a_2000,_instant_query/engine=Mimir-10                                                19.98m ± 1%   11.65m ±  1%  -41.69% (p=0.002 n=6)
Query/a_2000{l=~"[13579].*"}_/_a_2000,_range_query_with_100_steps/engine=Mimir-10                                   37.58m ± 1%   22.33m ±  0%  -40.59% (p=0.002 n=6)
Query/a_2000{l=~"[13579].*"}_/_a_2000,_range_query_with_1000_steps/engine=Mimir-10                                  186.4m ± 2%   112.4m ±  1%  -39.69% (p=0.002 n=6)
Query/rate(a_1{l=~"[13579].*"}[1m])_/_rate(a_1[1m]),_instant_query/engine=Mimir-10                                  343.6µ ± 3%   160.2µ ±  1%  -53.37% (p=0.002 n=6)
Query/rate(a_1{l=~"[13579].*"}[1m])_/_rate(a_1[1m]),_range_query_with_100_steps/engine=Mimir-10                     553.4µ ± 3%   171.2µ ±  1%  -69.06% (p=0.002 n=6)
Query/rate(a_1{l=~"[13579].*"}[1m])_/_rate(a_1[1m]),_range_query_with_1000_steps/engine=Mimir-10                    724.4µ ± 1%   181.9µ ±  1%  -74.89% (p=0.002 n=6)
Query/rate(a_100{l=~"[13579].*"}[1m])_/_rate(a_100[1m]),_instant_query/engine=Mimir-10                             1003.9µ ± 7%   525.5µ ±  4%  -47.65% (p=0.002 n=6)
Query/rate(a_100{l=~"[13579].*"}[1m])_/_rate(a_100[1m]),_range_query_with_100_steps/engine=Mimir-10                 2.902m ± 1%   1.674m ±  2%  -42.32% (p=0.002 n=6)
Query/rate(a_100{l=~"[13579].*"}[1m])_/_rate(a_100[1m]),_range_query_with_1000_steps/engine=Mimir-10               12.473m ± 0%   7.954m ±  0%  -36.23% (p=0.002 n=6)
Query/rate(a_2000{l=~"[13579].*"}[1m])_/_rate(a_2000[1m]),_instant_query/engine=Mimir-10                            9.280m ± 0%   5.899m ±  0%  -36.44% (p=0.002 n=6)
Query/rate(a_2000{l=~"[13579].*"}[1m])_/_rate(a_2000[1m]),_range_query_with_100_steps/engine=Mimir-10               47.21m ± 1%   27.78m ±  0%  -41.15% (p=0.002 n=6)
Query/rate(a_2000{l=~"[13579].*"}[1m])_/_rate(a_2000[1m]),_range_query_with_1000_steps/engine=Mimir-10              255.6m ± 0%   152.8m ±  1%  -40.23% (p=0.002 n=6)
Query/sum(a_1{l=~"[13579].*"})_/_sum(a_1),_instant_query/engine=Mimir-10                                            547.5µ ± 0%   165.6µ ±  1%  -69.74% (p=0.002 n=6)
Query/sum(a_1{l=~"[13579].*"})_/_sum(a_1),_range_query_with_100_steps/engine=Mimir-10                               545.2µ ± 0%   168.3µ ±  1%  -69.13% (p=0.002 n=6)
Query/sum(a_1{l=~"[13579].*"})_/_sum(a_1),_range_query_with_1000_steps/engine=Mimir-10                              888.9µ ± 1%   185.3µ ±  3%  -79.15% (p=0.002 n=6)
Query/sum(a_100{l=~"[13579].*"})_/_sum(a_100),_instant_query/engine=Mimir-10                                       1628.0µ ± 0%   791.5µ ±  1%  -51.38% (p=0.002 n=6)
Query/sum(a_100{l=~"[13579].*"})_/_sum(a_100),_range_query_with_100_steps/engine=Mimir-10                           2.429m ± 0%   1.329m ±  0%  -45.30% (p=0.002 n=6)
Query/sum(a_100{l=~"[13579].*"})_/_sum(a_100),_range_query_with_1000_steps/engine=Mimir-10                          9.383m ± 3%   5.789m ±  1%  -38.30% (p=0.002 n=6)
Query/sum(a_2000{l=~"[13579].*"})_/_sum(a_2000),_instant_query/engine=Mimir-10                                      18.80m ± 1%   10.32m ±  1%  -45.12% (p=0.002 n=6)
Query/sum(a_2000{l=~"[13579].*"})_/_sum(a_2000),_range_query_with_100_steps/engine=Mimir-10                         36.30m ± 1%   20.46m ±  1%  -43.64% (p=0.002 n=6)
Query/sum(a_2000{l=~"[13579].*"})_/_sum(a_2000),_range_query_with_1000_steps/engine=Mimir-10                        179.9m ± 0%   105.4m ±  1%  -41.44% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13579].*"}[1m]))_/_sum(rate(a_1[1m])),_instant_query/engine=Mimir-10                        345.8µ ± 0%   164.2µ ±  1%  -52.51% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13579].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_100_steps/engine=Mimir-10           556.5µ ± 2%   177.9µ ±  3%  -68.03% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13579].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_1000_steps/engine=Mimir-10          726.8µ ± 2%   185.5µ ±  1%  -74.48% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13579].*"}[1m]))_/_sum(rate(a_100[1m])),_instant_query/engine=Mimir-10                    995.8µ ± 3%   503.7µ ±  5%  -49.42% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13579].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_100_steps/engine=Mimir-10       2.876m ± 0%   1.627m ±  1%  -43.43% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13579].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_1000_steps/engine=Mimir-10     12.311m ± 1%   7.842m ±  1%  -36.30% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13579].*"}[1m]))_/_sum(rate(a_2000[1m])),_instant_query/engine=Mimir-10                  8.174m ± 1%   4.581m ±  1%  -43.96% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13579].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_100_steps/engine=Mimir-10     45.77m ± 1%   26.15m ±  1%  -42.86% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13579].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_1000_steps/engine=Mimir-10    250.2m ± 2%   147.1m ±  1%  -41.21% (p=0.002 n=6)
Query/sum(a_1{l=~"[13].*"})_/_sum(a_1),_instant_query/engine=Mimir-10                                               483.6µ ± 3%   164.7µ ±  1%  -65.95% (p=0.002 n=6)
Query/sum(a_1{l=~"[13].*"})_/_sum(a_1),_range_query_with_100_steps/engine=Mimir-10                                  481.2µ ± 0%   167.7µ ±  1%  -65.15% (p=0.002 n=6)
Query/sum(a_1{l=~"[13].*"})_/_sum(a_1),_range_query_with_1000_steps/engine=Mimir-10                                 766.8µ ± 0%   184.2µ ±  1%  -75.97% (p=0.002 n=6)
Query/sum(a_100{l=~"[13].*"})_/_sum(a_100),_instant_query/engine=Mimir-10                                          1387.6µ ± 0%   787.5µ ±  3%  -43.25% (p=0.002 n=6)
Query/sum(a_100{l=~"[13].*"})_/_sum(a_100),_range_query_with_100_steps/engine=Mimir-10                              2.022m ± 0%   1.320m ±  2%  -34.73% (p=0.002 n=6)
Query/sum(a_100{l=~"[13].*"})_/_sum(a_100),_range_query_with_1000_steps/engine=Mimir-10                             7.574m ± 0%   5.769m ±  5%  -23.83% (p=0.002 n=6)
Query/sum(a_2000{l=~"[13].*"})_/_sum(a_2000),_instant_query/engine=Mimir-10                                         16.93m ± 1%   10.33m ±  1%  -39.00% (p=0.002 n=6)
Query/sum(a_2000{l=~"[13].*"})_/_sum(a_2000),_range_query_with_100_steps/engine=Mimir-10                            32.75m ± 1%   20.47m ±  1%  -37.51% (p=0.002 n=6)
Query/sum(a_2000{l=~"[13].*"})_/_sum(a_2000),_range_query_with_1000_steps/engine=Mimir-10                           162.8m ± 1%   105.3m ±  1%  -35.36% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13].*"}[1m]))_/_sum(rate(a_1[1m])),_instant_query/engine=Mimir-10                           312.6µ ± 1%   164.3µ ±  1%  -47.46% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_100_steps/engine=Mimir-10              489.9µ ± 3%   174.8µ ±  1%  -64.32% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_1000_steps/engine=Mimir-10             633.4µ ± 0%   187.3µ ±  2%  -70.43% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13].*"}[1m]))_/_sum(rate(a_100[1m])),_instant_query/engine=Mimir-10                       875.5µ ± 0%   498.1µ ±  5%  -43.11% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_100_steps/engine=Mimir-10          2.382m ± 1%   1.614m ±  0%  -32.26% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_1000_steps/engine=Mimir-10         9.855m ± 0%   7.815m ±  3%  -20.70% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13].*"}[1m]))_/_sum(rate(a_2000[1m])),_instant_query/engine=Mimir-10                     7.452m ± 0%   4.555m ±  1%  -38.88% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_100_steps/engine=Mimir-10        41.25m ± 1%   26.12m ±  3%  -36.68% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_1000_steps/engine=Mimir-10       226.1m ± 1%   146.6m ± 25%  -35.17% (p=0.002 n=6)
geomean                                                                                                             4.331m        2.078m        -52.03%


                                                                                                                 │  before.txt  │               after.txt                │
                                                                                                                 │      B       │       B         vs base                │
Query/a_1{l=~"[13579].*"}_/_a_1,_instant_query/engine=Mimir-10                                                     60.66Mi ± 1%   114.11Mi ± 46%   +88.12% (p=0.002 n=6)
Query/a_1{l=~"[13579].*"}_/_a_1,_range_query_with_100_steps/engine=Mimir-10                                        60.73Mi ± 1%   114.52Mi ±  2%   +88.59% (p=0.002 n=6)
Query/a_1{l=~"[13579].*"}_/_a_1,_range_query_with_1000_steps/engine=Mimir-10                                       60.00Mi ± 1%   109.90Mi ±  2%   +83.16% (p=0.002 n=6)
Query/a_100{l=~"[13579].*"}_/_a_100,_instant_query/engine=Mimir-10                                                 61.82Mi ± 1%    62.09Mi ±  1%         ~ (p=0.065 n=6)
Query/a_100{l=~"[13579].*"}_/_a_100,_range_query_with_100_steps/engine=Mimir-10                                    61.97Mi ± 0%    62.20Mi ±  1%         ~ (p=0.258 n=6)
Query/a_100{l=~"[13579].*"}_/_a_100,_range_query_with_1000_steps/engine=Mimir-10                                   63.48Mi ± 1%    63.76Mi ±  1%         ~ (p=0.485 n=6)
Query/a_2000{l=~"[13579].*"}_/_a_2000,_instant_query/engine=Mimir-10                                               65.20Mi ± 1%    64.24Mi ±  1%    -1.47% (p=0.026 n=6)
Query/a_2000{l=~"[13579].*"}_/_a_2000,_range_query_with_100_steps/engine=Mimir-10                                  72.30Mi ± 2%    71.51Mi ±  1%         ~ (p=0.058 n=6)
Query/a_2000{l=~"[13579].*"}_/_a_2000,_range_query_with_1000_steps/engine=Mimir-10                                 120.3Mi ± 2%    115.3Mi ±  2%    -4.14% (p=0.002 n=6)
Query/rate(a_1{l=~"[13579].*"}[1m])_/_rate(a_1[1m]),_instant_query/engine=Mimir-10                                 61.35Mi ± 1%   115.66Mi ± 46%   +88.53% (p=0.002 n=6)
Query/rate(a_1{l=~"[13579].*"}[1m])_/_rate(a_1[1m]),_range_query_with_100_steps/engine=Mimir-10                    61.03Mi ± 1%   110.92Mi ± 48%   +81.75% (p=0.002 n=6)
Query/rate(a_1{l=~"[13579].*"}[1m])_/_rate(a_1[1m]),_range_query_with_1000_steps/engine=Mimir-10                   60.26Mi ± 1%   109.60Mi ± 42%   +81.89% (p=0.002 n=6)
Query/rate(a_100{l=~"[13579].*"}[1m])_/_rate(a_100[1m]),_instant_query/engine=Mimir-10                             62.27Mi ± 1%    62.36Mi ±  1%         ~ (p=0.937 n=6)
Query/rate(a_100{l=~"[13579].*"}[1m])_/_rate(a_100[1m]),_range_query_with_100_steps/engine=Mimir-10                62.21Mi ± 1%    61.85Mi ±  1%         ~ (p=0.193 n=6)
Query/rate(a_100{l=~"[13579].*"}[1m])_/_rate(a_100[1m]),_range_query_with_1000_steps/engine=Mimir-10               62.70Mi ± 2%    63.12Mi ±  1%         ~ (p=0.455 n=6)
Query/rate(a_2000{l=~"[13579].*"}[1m])_/_rate(a_2000[1m]),_instant_query/engine=Mimir-10                           65.68Mi ± 1%    65.32Mi ±  1%         ~ (p=0.394 n=6)
Query/rate(a_2000{l=~"[13579].*"}[1m])_/_rate(a_2000[1m]),_range_query_with_100_steps/engine=Mimir-10              72.07Mi ± 1%    70.16Mi ±  1%    -2.66% (p=0.002 n=6)
Query/rate(a_2000{l=~"[13579].*"}[1m])_/_rate(a_2000[1m]),_range_query_with_1000_steps/engine=Mimir-10             116.1Mi ± 2%    115.1Mi ±  1%         ~ (p=0.310 n=6)
Query/sum(a_1{l=~"[13579].*"})_/_sum(a_1),_instant_query/engine=Mimir-10                                           60.78Mi ± 2%   114.07Mi ± 46%   +87.67% (p=0.002 n=6)
Query/sum(a_1{l=~"[13579].*"})_/_sum(a_1),_range_query_with_100_steps/engine=Mimir-10                              60.82Mi ± 1%   112.46Mi ±  1%   +84.91% (p=0.002 n=6)
Query/sum(a_1{l=~"[13579].*"})_/_sum(a_1),_range_query_with_1000_steps/engine=Mimir-10                             60.23Mi ± 0%   108.54Mi ± 44%   +80.19% (p=0.002 n=6)
Query/sum(a_100{l=~"[13579].*"})_/_sum(a_100),_instant_query/engine=Mimir-10                                       61.77Mi ± 2%    61.68Mi ±  1%         ~ (p=0.589 n=6)
Query/sum(a_100{l=~"[13579].*"})_/_sum(a_100),_range_query_with_100_steps/engine=Mimir-10                          61.98Mi ± 1%    61.98Mi ±  1%         ~ (p=0.937 n=6)
Query/sum(a_100{l=~"[13579].*"})_/_sum(a_100),_range_query_with_1000_steps/engine=Mimir-10                         61.98Mi ± 2%    62.08Mi ±  1%         ~ (p=0.669 n=6)
Query/sum(a_2000{l=~"[13579].*"})_/_sum(a_2000),_instant_query/engine=Mimir-10                                     64.29Mi ± 2%    63.30Mi ±  1%    -1.53% (p=0.026 n=6)
Query/sum(a_2000{l=~"[13579].*"})_/_sum(a_2000),_range_query_with_100_steps/engine=Mimir-10                        64.39Mi ± 1%    63.18Mi ±  1%    -1.88% (p=0.004 n=6)
Query/sum(a_2000{l=~"[13579].*"})_/_sum(a_2000),_range_query_with_1000_steps/engine=Mimir-10                       69.88Mi ± 2%    65.75Mi ±  1%    -5.90% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13579].*"}[1m]))_/_sum(rate(a_1[1m])),_instant_query/engine=Mimir-10                       61.86Mi ± 1%   111.95Mi ± 42%   +80.98% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13579].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_100_steps/engine=Mimir-10          61.28Mi ± 1%   108.70Mi ± 46%   +77.37% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13579].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_1000_steps/engine=Mimir-10         60.55Mi ± 1%   130.13Mi ± 20%  +114.90% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13579].*"}[1m]))_/_sum(rate(a_100[1m])),_instant_query/engine=Mimir-10                   62.34Mi ± 1%    62.40Mi ±  1%         ~ (p=0.589 n=6)
Query/sum(rate(a_100{l=~"[13579].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_100_steps/engine=Mimir-10      61.84Mi ± 1%    62.43Mi ±  1%         ~ (p=0.327 n=6)
Query/sum(rate(a_100{l=~"[13579].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_1000_steps/engine=Mimir-10     61.12Mi ± 2%    62.02Mi ±  1%    +1.47% (p=0.039 n=6)
Query/sum(rate(a_2000{l=~"[13579].*"}[1m]))_/_sum(rate(a_2000[1m])),_instant_query/engine=Mimir-10                 65.31Mi ± 1%    64.52Mi ±  1%    -1.21% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13579].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_100_steps/engine=Mimir-10    64.13Mi ± 1%    63.29Mi ±  2%    -1.32% (p=0.026 n=6)
Query/sum(rate(a_2000{l=~"[13579].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_1000_steps/engine=Mimir-10   69.41Mi ± 1%    65.68Mi ±  1%    -5.38% (p=0.002 n=6)
Query/sum(a_1{l=~"[13].*"})_/_sum(a_1),_instant_query/engine=Mimir-10                                              60.67Mi ± 2%   114.25Mi ± 45%   +88.31% (p=0.002 n=6)
Query/sum(a_1{l=~"[13].*"})_/_sum(a_1),_range_query_with_100_steps/engine=Mimir-10                                 61.26Mi ± 0%   112.08Mi ± 47%   +82.96% (p=0.002 n=6)
Query/sum(a_1{l=~"[13].*"})_/_sum(a_1),_range_query_with_1000_steps/engine=Mimir-10                                60.55Mi ± 1%   131.55Mi ± 19%  +117.25% (p=0.002 n=6)
Query/sum(a_100{l=~"[13].*"})_/_sum(a_100),_instant_query/engine=Mimir-10                                          61.94Mi ± 1%    61.92Mi ±  1%         ~ (p=0.907 n=6)
Query/sum(a_100{l=~"[13].*"})_/_sum(a_100),_range_query_with_100_steps/engine=Mimir-10                             61.95Mi ± 1%    62.20Mi ±  1%         ~ (p=0.485 n=6)
Query/sum(a_100{l=~"[13].*"})_/_sum(a_100),_range_query_with_1000_steps/engine=Mimir-10                            62.44Mi ± 1%    62.04Mi ±  0%         ~ (p=0.141 n=6)
Query/sum(a_2000{l=~"[13].*"})_/_sum(a_2000),_instant_query/engine=Mimir-10                                        64.41Mi ± 1%    63.52Mi ±  2%         ~ (p=0.093 n=6)
Query/sum(a_2000{l=~"[13].*"})_/_sum(a_2000),_range_query_with_100_steps/engine=Mimir-10                           63.91Mi ± 1%    63.20Mi ±  1%    -1.10% (p=0.026 n=6)
Query/sum(a_2000{l=~"[13].*"})_/_sum(a_2000),_range_query_with_1000_steps/engine=Mimir-10                          70.13Mi ± 1%    66.57Mi ±  3%    -5.08% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13].*"}[1m]))_/_sum(rate(a_1[1m])),_instant_query/engine=Mimir-10                          61.72Mi ± 1%   112.31Mi ± 47%   +81.97% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_100_steps/engine=Mimir-10             60.90Mi ± 2%   109.73Mi ± 48%   +80.19% (p=0.002 n=6)
Query/sum(rate(a_1{l=~"[13].*"}[1m]))_/_sum(rate(a_1[1m])),_range_query_with_1000_steps/engine=Mimir-10            60.73Mi ± 1%   107.55Mi ± 42%   +77.10% (p=0.002 n=6)
Query/sum(rate(a_100{l=~"[13].*"}[1m]))_/_sum(rate(a_100[1m])),_instant_query/engine=Mimir-10                      62.24Mi ± 1%    62.62Mi ±  1%         ~ (p=0.143 n=6)
Query/sum(rate(a_100{l=~"[13].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_100_steps/engine=Mimir-10         61.60Mi ± 2%    62.23Mi ±  1%         ~ (p=0.087 n=6)
Query/sum(rate(a_100{l=~"[13].*"}[1m]))_/_sum(rate(a_100[1m])),_range_query_with_1000_steps/engine=Mimir-10        61.91Mi ± 1%    62.09Mi ±  1%         ~ (p=0.331 n=6)
Query/sum(rate(a_2000{l=~"[13].*"}[1m]))_/_sum(rate(a_2000[1m])),_instant_query/engine=Mimir-10                    65.09Mi ± 1%    64.07Mi ±  0%    -1.57% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_100_steps/engine=Mimir-10       64.49Mi ± 1%    63.29Mi ±  1%    -1.87% (p=0.002 n=6)
Query/sum(rate(a_2000{l=~"[13].*"}[1m]))_/_sum(rate(a_2000[1m])),_range_query_with_1000_steps/engine=Mimir-10      69.41Mi ± 1%    65.26Mi ±  2%    -5.99% (p=0.002 n=6)
geomean                                                                                                            64.55Mi         78.89Mi         +22.22%

Which issue(s) this PR fixes or relates to

(none)

Checklist

  • Tests updated.
  • [n/a] Documentation added.
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]. If changelog entry is not needed, please add the changelog-not-needed label to the PR.
  • [n/a] about-versioning.md updated with experimental features.

Note

Medium Risk
Touches core query planning and streaming evaluation/buffering logic; while gated behind an experimental flag and plan versioning, mistakes could cause incorrect query results or memory/CPU regressions in eligible queries.

Overview
Adds experimental subset selector elimination (SSE) to the Mimir Query Engine, allowing queries like foo{env="bar"} / foo to evaluate the broader selector once and apply per-consumer filtering via new plan node DuplicateFilter.

Extends the common subexpression elimination pass to detect duplicate vs subset selectors, track new labeled elimination metrics, and only apply SSE when supported by QueryPlanV7 and safe to push filtering past certain functions/aggregations. Updates duplication buffering/operators to support filtered consumers and avoid buffering series that no remaining consumer will read.

Wires a new flag/config option -querier.mimir-query-engine.enable-subset-selector-elimination (default false), updates docs/help/changelog, and expands benchmarks/tests to cover SSE behavior and annotation differences.

Written by Cursor Bugbot for commit 536be67. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

@charleskorn charleskorn force-pushed the charleskorn/subset-selector-elimination branch from 45147bb to a25485e Compare February 16, 2026 09:03
@cursor

This comment has been minimized.

@charleskorn
Copy link
Contributor Author

@cursor push a18ee60

cursoragent and others added 2 commits February 17, 2026 02:42
Return the actual error from introduceDuplicateNode instead of nil when an error occurs. This ensures that failures during duplicate node introduction are properly propagated instead of being silently ignored, which could lead to inconsistent query plan state.

Applied via @cursor push command
@cursor

This comment has been minimized.

@charleskorn charleskorn marked this pull request as ready for review February 17, 2026 04:27
@charleskorn charleskorn requested review from a team and tacole02 as code owners February 17, 2026 04:27
@cursor

This comment has been minimized.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is ON. A Cloud Agent has been kicked off to fix the reported issue.

@cursor
Copy link

cursor bot commented Feb 17, 2026

Bugbot Autofix prepared fixes for 1 of the 1 bugs found in the latest run.

  • ✅ Fixed: label_join/label_replace missing __name__ drop check
    • Added the missing name label check to match the behavior of other name-dropping functions when delayed name removal is disabled.

Create PR

Or push these changes by commenting:

@cursor push 1c3d753413
Preview (1c3d753413)
diff --git a/pkg/streamingpromql/optimize/plan/commonsubexpressionelimination/optimization_pass.go b/pkg/streamingpromql/optimize/plan/commonsubexpressionelimination/optimization_pass.go
--- a/pkg/streamingpromql/optimize/plan/commonsubexpressionelimination/optimization_pass.go
+++ b/pkg/streamingpromql/optimize/plan/commonsubexpressionelimination/optimization_pass.go
@@ -710,8 +710,14 @@
 			return false, true
 		}
 
-		return !group.haveAnyFiltersForLabel(destinationLabelName), true
+		if group.haveAnyFiltersForLabel(destinationLabelName) {
+			return false, true
+		}
 
+		// These functions drop the __name__ label if delayed name removal is not enabled, so it's only safe to apply
+		// filtering after these functions if delayed name removal is enabled, or there is no filtering by __name__.
+		return delayedNameRemovalEnabled || !group.haveAnyFiltersForLabel(model.MetricNameLabel), true
+
 	case functions.FUNCTION_HISTOGRAM_FRACTION, functions.FUNCTION_HISTOGRAM_QUANTILE:
 		// These functions drop the 'le' label on native histograms, so we can never apply filtering after the function
 		// if the filter is on that label.

Copy link
Contributor

@tacole02 tacole02 left a comment

Choose a reason for hiding this comment

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

Docs look good! Thank you!

Copy link
Contributor

@56quarters 56quarters left a comment

Choose a reason for hiding this comment

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

I haven't finished going through this but it's EOD here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments