简介
正如标题所示,子查询是查询的一部分,它允许您在查询中执行范围查询,这是以前不可能的。这是一项长期存在的功能请求:prometheus/prometheus/1227。
支持子查询的拉取请求最近已合并到 Prometheus 中,并将在 Prometheus 2.7 中提供。下面让我们了解更多信息。
动机
有时,您可能希望使用较低分辨率/范围(例如 5m
)的 rate
来发现问题,同时为较高范围(例如 max_over_time
对于 1h
)聚合此数据。
以前,以上情况对于单个 PromQL 查询是不可能的。如果您想对查询进行范围选择以用于警报规则或绘图,则需要基于该查询创建记录规则,并对记录规则创建的指标执行范围选择。示例:max_over_time(rate(my_counter_total[5m])[1h])
。
当您想快速获取跨越几天或几周的数据结果时,可能需要等待相当长的时间,直到您的记录规则中有足够的数据才能使用。忘记添加记录规则可能会令人沮丧。为查询的每个步骤创建记录规则也很繁琐。
有了子查询支持,所有的等待和沮丧都迎刃而解。
子查询
子查询类似于 /api/v1/query_range API 调用,但嵌入在即时查询中。子查询的结果是一个范围向量。
Prometheus 团队在慕尼黑举行的 2018 年 Prometheus 开发者峰会上就子查询的语法达成了共识。这些是峰会关于子查询支持的笔记,以及用于实现子查询支持的语法设计的简要设计文档。
<instant_query> '[' <range> ':' [ <resolution> ] ']' [ offset <duration> ]
-
<instant_query>
等同于/query_range
API 中的query
字段。 -
<range>
和offset <duration>
类似于范围选择器。 -
<resolution>
是可选的,它等同于/query_range
API 中的step
。
当未指定分辨率时,全局评估间隔将作为子查询的默认分辨率。此外,子查询的步长是独立对齐的,不依赖于父查询的评估时间。
示例
min_over_time
函数内部的子查询返回 http_requests_total
指标在过去 30 分钟内的 5 分钟速率,分辨率为 1 分钟。这等同于一个 /query_range
API 调用,其中 query=rate(http_requests_total[5m]), end=<now>, start=<now>-30m, step=1m
,并取所有接收值的最小值。
min_over_time( rate(http_requests_total[5m])[30m:1m] )
分解
-
rate(http_requests_total[5m])[30m:1m]
是子查询,其中rate(http_requests_total[5m])
是要执行的查询。 -
rate(http_requests_total[5m])
从start=<now>-30m
执行到end=<now>
,分辨率为1m
。请注意,start
时间与步长1m
独立对齐(对齐的步长为0m 1m 2m 3m ...
)。 - 最后,以上所有评估的结果都传递给
min_over_time()
。
下面是一个嵌套子查询和使用默认分辨率的示例。最内层的子查询获取 distance_covered_meters_total
在一个时间范围内的速率。我们使用它来获取这些速率的 deriv()
,同样也是在一个时间范围内。最后取所有导数的最大值。请注意,最内层子查询的 <now>
时间是相对于外层子查询 deriv()
的评估时间。
max_over_time( deriv( rate(distance_covered_meters_total[1m])[5m:1m] )[10m:] )
在大多数情况下,您将需要默认评估间隔,这是规则默认评估的间隔。自定义分辨率在您希望计算频率较低/较高的情况下很有帮助,例如您可能希望计算频率较低的昂贵查询。
结语
尽管子查询替代记录规则非常方便,但不必要地使用它们会对性能产生影响。出于效率考虑,重量级的子查询最终应转换为记录规则。
也不建议在记录规则内包含子查询。如果确实需要在记录规则中使用子查询,不如创建更多的记录规则。