-
Notifications
You must be signed in to change notification settings - Fork 537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
frontend: update query pruning #10026
base: main
Are you sure you want to change the base?
Conversation
9dcc588
to
c70d552
Compare
97a767d
to
98d8813
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can further prune the expression in some cases:
{ | ||
// "and on()" is not on top level, "or" has lower precedence. | ||
`(avg(rate(foo[1m]))) and on() (vector(0) == 1) or avg(rate(bar[1m]))`, | ||
`(vector(0) == 1) or avg(rate(bar[1m]))`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we simplify this further, to avg(rate(bar[1m]))
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's more complicated. The main point is to avoid loading chunks and (vector(0)==1)
doesn't load chunks, so should be very efficient.
We can add that logic in a new PR, seems to be independent from this optimization, wdyt?
But having two algorithms raises the question of whether they need to be run repeatedly to optimize away everything, so it gets even more complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that removing (vector(0)==1)
from an OR expression is different from removing it from an AND expression, which is what I mean by more complicated . Outside my scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test for this? We should document that in a test so nobody comes tomorrow and "optimizes further".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having two algorithms raises the question of whether they need to be run repeatedly to optimize away everything, so it gets even more complicated.
If we optimise the leaf node expressions first and work our way back up the tree, can't we do both and
and or
in one pass?
But if you want to limit this to and
and come back to or
later, that's fine by me, please just make this clear with a test or a comment as Oleg suggests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding both
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, actually I had 3 tests on this already so just improved the comments
{ | ||
// "and on()" is not on top level, due to left-right associativity. | ||
`(avg(rate(foo[1m]))) and on() (vector(0) == 1) and avg(rate(bar[1m]))`, | ||
`(vector(0) == 1) and avg(rate(bar[1m]))`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we simplify this further, to vector(0) == 1
?
}, | ||
{ // The const expression is on the wrong side. | ||
`(vector(0) == 1) and on() (avg(rate(foo[1m])))`, | ||
`(vector(0) == 1) and on() (avg(rate(foo[1m])))`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as below - I think this can be simplified to vector(0) == 1
.
}, | ||
{ // Matching on labels. | ||
`(avg(rate(foo[1m]))) and on(id) (vector(0) == 1)`, | ||
`(avg(rate(foo[1m]))) and on(id) (vector(0) == 1)`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this be simplified to vector(0) == 1
? The right side will never produce a result, so we'll never return anything from the left side.
}, | ||
{ // Not "on" expression. | ||
`(avg(rate(foo[1m]))) and ignoring() (vector(0) == 1)`, | ||
`(avg(rate(foo[1m]))) and ignoring() (vector(0) == 1)`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above - the right side will never produce a result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good at first glance. (I assume you don't want a code-level review from me, just that the idea is correct.)
a1440c4
to
6901f7d
Compare
The current method of excluding/including sub query results in PromQL by comparing to -Inf or +Inf is no longer valid after prometheus/prometheus#15245 due to comparison of native histograms to a float with < or > result in Jeanette's warning, not empty set. The new method uses logical AND operation to intersect the sub query with either a const vector() or an empty vector(). E.g. subquery and on() (vector(1)==1) subquery and on() (vector(-1)==1) which become: subquery (vector(-1)==1) Note that although in theory (vector(-1)==1) could be dropped in some cases, it depends on the context and out of scope for this PR. Signed-off-by: György Krajcsovits <[email protected]>
6901f7d
to
f6c554a
Compare
@@ -77,6 +77,7 @@ | |||
* [ENHANCEMENT] Ingester: Add `-blocks-storage.tsdb.bigger-out-of-order-blocks-for-old-samples` to build 24h blocks for out-of-order data belonging to the previous days instead of building smaller 2h blocks. This reduces pressure on compactors and ingesters when the out-of-order samples span multiple days in the past. #9844 #10033 #10035 | |||
* [ENHANCEMENT] Distributor: allow a different limit for info series (series ending in `_info`) label count, via `-validation.max-label-names-per-info-series`. #10028 | |||
* [ENHANCEMENT] Ingester: do not reuse labels, samples and histograms slices in the write request if there are more entries than 10x the pre-allocated size. This should help to reduce the in-use memory in case of few requests with a very large number of labels, samples or histograms. #10040 | |||
* [ENHANCEMENT] Query-Frontend: prune `<subquery> and on() (vector(x)==y)` style queries and no longer prune `<subquery> < -Inf`. Triggered by https://github.com/prometheus/prometheus/pull/15245. #10026 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: no longer prune
>> stop pruning
What this PR does
The current method of excluding/including sub query results in PromQL by comparing to -Inf or +Inf is no longer valid after prometheus/prometheus#15245 due to comparison of native histograms to a float with < or > result in Jeanette's warning, not empty set.
To ease migration away from the old wrong logic, I'm adding the new logic first.
The new method uses logical AND operation to intersect the sub query with either a const vector() or an empty vector(). E.g.
which becomes:
and conversely
becomes
Note
We cannot just drop
(vector(-1)==1)
altogether , because of this example:removal of the whole right side would allow results from the
other_subquery
which is not correct. Solving this is out of scope.Which issue(s) this PR fixes or relates to
Fixes N/A
Checklist
CHANGELOG.md
updated - the order of entries should be[CHANGE]
,[FEATURE]
,[ENHANCEMENT]
,[BUGFIX]
.about-versioning.md
updated with experimental features.