Skip to content

MQE: add support for filtering in multi-aggregation nodes#14457

Merged
charleskorn merged 3 commits intomainfrom
charleskorn/subset-selector-elimination-multi-aggregation
Feb 27, 2026
Merged

MQE: add support for filtering in multi-aggregation nodes#14457
charleskorn merged 3 commits intomainfrom
charleskorn/subset-selector-elimination-multi-aggregation

Conversation

@charleskorn
Copy link
Contributor

@charleskorn charleskorn commented Feb 23, 2026

What this PR does

This PR is derived from #14377, and extends the existing multi-aggregation logic so that no buffering is required for expressions like sum(request_count{status="success}) / sum(request_count).

See #14377 for more context.

This PR builds on #14455 and #14456.

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
Changes MQE execution/planning for multi-aggregation to apply per-consumer label filters and introduces QueryPlanV8, which could affect query correctness/performance and cross-version compatibility if any edge cases are missed.

Overview
Enables multi-aggregation consumers to carry and apply selector filters, so expressions like sum(foo{...}) / sum(foo) can share a single underlying scan without buffering.

This extends the multi-aggregation plan/node protobuf (MultiAggregationInstanceDetails) and materialization to pass matchers into MultiAggregatorInstanceOperator, which now precomputes a per-series bitmap and skips accumulation for instances whose filters don’t match.

The multi-aggregation optimization pass is updated to fold AggregateExpression over DuplicateFilter into filtered MultiAggregationInstance when the supported plan version is >= QueryPlanV8; MaximumSupportedQueryPlanVersion is bumped to V8, tests are expanded for subset-selector scenarios and version gating, and the changelog entry is updated.

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

@charleskorn charleskorn force-pushed the charleskorn/subset-selector-elimination-multi-aggregation branch from 66b2e02 to 973cee1 Compare February 23, 2026 01:15
@charleskorn charleskorn marked this pull request as ready for review February 23, 2026 01:58
@charleskorn charleskorn requested a review from a team as a code owner February 23, 2026 01:58
@charleskorn charleskorn force-pushed the charleskorn/subset-selector-elimination-multi-aggregation branch from 973cee1 to 41ae315 Compare February 23, 2026 02:24
@charleskorn charleskorn force-pushed the charleskorn/subset-selector-elimination-multi-aggregation branch from 41ae315 to 38c5d3c Compare February 24, 2026 22:58
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

This comment was marked as outdated.

Base automatically changed from charleskorn/subset-selector-elimination-planning-and-eval to main February 26, 2026 03:54
@charleskorn charleskorn force-pushed the charleskorn/subset-selector-elimination-multi-aggregation branch from 38c5d3c to 57c612c Compare February 26, 2026 03:56
Copy link
Contributor

@lamida lamida left a comment

Choose a reason for hiding this comment

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

I left some comments but more on clarifying things. I can approve once it is clarified.


m.unfilteredSeriesBitmap, err = types.BoolSlicePool.Get(len(unfilteredSeries), m.group.memoryConsumptionTracker)
if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

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

In this case do we need to return types.SeriesMetadataSlicePool.Put?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Our general approach elsewhere has been that we don't mind not returning things to pools if something goes wrong, so I don't think we should do something different here.

if filteringSupported {
// If the parent is a DuplicateFilter, we need to look at the grandparent.
if _, isDuplicateFilter := parent.(*commonsubexpressionelimination.DuplicateFilter); isDuplicateFilter {
parent = path[len(path)-2]
Copy link
Contributor

Choose a reason for hiding this comment

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

What prevent this going out of bound?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If there is a duplicate expression, there must be at least one node higher in the path (ie. a parent) - it's not possible to construct a PromQL expression containing a duplicate subexpression where the duplicated expression doesn't have a parent of its own, such as a binary expression or function call.

@charleskorn charleskorn requested a review from lamida February 26, 2026 22:54
Copy link
Contributor

@lamida lamida left a comment

Choose a reason for hiding this comment

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

🚀

@charleskorn charleskorn merged commit 33f60c4 into main Feb 27, 2026
46 checks passed
@charleskorn charleskorn deleted the charleskorn/subset-selector-elimination-multi-aggregation branch February 27, 2026 05:12
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.

2 participants