【博客619】PromQL如何实现Left joins以及不同metrics之间的复杂联合查询
在限定匹配标签后,右向量中的元素可能匹配到多个左向量中的元素 因此该表达式的匹配模式为多对一,需要使用group修饰符group_left指定左向量具有更好的基数。多对一和一对多两种匹配模式指的是“一”侧的每一个向量元素可以与"多"侧的多个元素匹配的情况。在这种情况下,必须使用group修饰符:group_left或者group_right来确定哪一个向量具有更高的基数(充当“多”的角色)。多对一
PromQL如何实现Left joins以及不同metrics之间的复杂联合查询
1、场景
我们需要在PromQL中实现类似SQL中的连接查询:
SELECT a.value*b.value, * FROM a, b
2、不同metrics之间的复杂联合查询
-
瞬时向量与瞬时向量之间进行数学运算:
例如:根据node_disk_bytes_written和node_disk_bytes_read获取主机磁盘IO的总量:
node_disk_bytes_written + node_disk_bytes_read这个表达式工作原理:
- 依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。同时新的时间序列将不会包含指标名称。
- 该表达式返回结果的示例如下所示:
{device=“sda”,instance=“localhost:9100”,job=“node_exporter”}=>1634967552@1518146427.807 + 864551424@1518146427.807
-
使用bool修饰符改变布尔运算符的行为
布尔运算符的默认行为是对时序数据进行过滤。而有时候需要的是真正的布尔结果。例如:
只需知道HTTP请求量是否>=1000,若大于等于1000则返回1(true)否则返回0(false)。这时可以使用bool修饰符改变布尔运算的默认行为。 例如:http_requests_total > bool 1000
使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果0或者1。从而形成一条新的时间序列:
http_requests_total{code=“200”,instance=“localhost:9090”,method=“get”} 1 -
一对一匹配
一对一匹配模式会从操作符两边表达式获取的瞬时向量依次比较并找到唯一匹配(标签完全一致)的样本值。
默认情况下,使用表达式:vector1 vector2
操作符两边表达式标签不一致,可用on(label list)或ignoring(label list)修改便签匹配行为。
- 使用ignoreing可以在匹配时忽略某些便签:
- {vector expr} 运算符 ignoring(
- 而on则用于将匹配行为限定在某些便签之内。
- {vector expr} 运算符 on(
例如当存在样本:
method_code:http_errors:rate5m{method=“get”, code=“500”} 24
method_code:http_errors:rate5m{method=“get”, code=“404”} 30
method_code:http_errors:rate5m{method=“put”, code=“501”} 3
method_code:http_errors:rate5m{method=“post”, code=“500”} 6
method_code:http_errors:rate5m{method=“post”, code=“404”} 21method:http_requests:rate5m{method=“get”} 600
method:http_requests:rate5m{method=“del”} 34
method:http_requests:rate5m{method=“post”} 120使用PromQL表达式:
method_code:http_errors:rate5m{code=“500”} / ignoring(code) method:http_requests:rate5m该表达式会返回在过去5分钟内,HTTP请求状态码为500的在所有请求中的比例。
如果没有使用ignoring(code),操作符两边表达式返回的瞬时向量中将找不到任何一个标签完全相同的匹配项,因此结果如下:{method=“get”} 0.04 // 24 / 600
{method=“post”} 0.05 // 6 / 120同时由于method为put和del的样本找不到匹配项,因此不会出现在结果当中。
- 使用ignoreing可以在匹配时忽略某些便签:
-
多对一和一对多:即下面的Left joins与Right joins
多对一和一对多两种匹配模式指的是“一”侧的每一个向量元素可以与"多"侧的多个元素匹配的情况。在这种情况下,必须使用group修饰符:group_left或者group_right来确定哪一个向量具有更高的基数(充当“多”的角色)。
-
聚合查询
-
常见聚合函数:
sum (calculate sum over dimensions)
min (select minimum over dimensions)
max (select maximum over dimensions)
avg (calculate the average over dimensions)
group (all values in the resulting vector are 1)
stddev (calculate population standard deviation over dimensions)
stdvar (calculate population standard variance over dimensions)
count (count number of elements in the vector)
count_values (count number of elements with the same value)
bottomk (smallest k elements by sample value)
topk (largest k elements by sample value)
quantile (calculate φ-quantile (0 ≤ φ ≤ 1) over dimensions) -
用法
- 运算符 [without|by (label list)] ([parameter,] {vector expr})
- 运算符([parameter,] {vector expr}) [without|by (label list)]
-
区别:
- without 从结果向量中删除列出的标签,而所有其他标签都保留在输出中。 by 做相反的事情并删除未在 by 子句中列出的标签,即使它们的标签值在向量的所有元素之间都是相同的
-
example:
- sum without (instance) (http_requests_total)
- sum by (application, group) (http_requests_total)
-
3、PromQL如何实现Left joins,即实现:多对一和一对多查询
group_left或者group_right:
多对一和一对多两种匹配模式指的是“一”侧的每一个向量元素可以与"多"侧的多个元素匹配的情况。在这种情况下,必须使用group修饰符:group_left或者group_right来确定哪一个向量具有更高的基数(充当“多”的角色)。
语法:
<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
场景:
多对一和一对多两种模式一定是出现在操作符两侧表达式返回的向量标签不一致的情况。因此需要使用ignoring和on修饰符来排除或者限定匹配的标签列表。
示例:
method_code:http_errors:rate5m{method="get", code="500"} 24
method_code:http_errors:rate5m{method="get", code="404"} 30
method_code:http_errors:rate5m{method="put", code="501"} 3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21
method:http_requests:rate5m{method="get"} 600
method:http_requests:rate5m{method="del"} 34
method:http_requests:rate5m{method="post"} 120
查询:
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
该表达式中,左向量method_code:http_errors:rate5m包含两个标签method和code。而右向量method:http_requests:rate5m中只包含一个标签method,因此匹配时需要使用ignoring限定匹配的标签为code。 在限定匹配标签后,右向量中的元素可能匹配到多个左向量中的元素 因此该表达式的匹配模式为多对一,需要使用group修饰符group_left指定左向量具有更好的基数。
最终的运算结果如下:
{method="get", code="500"} 0.04 // 24 / 600
{method="get", code="404"} 0.05 // 30 / 600
{method="post", code="500"} 0.05 // 6 / 120
{method="post", code="404"} 0.175 // 21 / 120
提醒:group修饰符只能在比较和数学运算符中使用。在逻辑运算and,unless和or才注意操作中默认与右向量中的所有元素进行匹配。
4、PromQL vs SQL
示例1:
SQL:
SELECT a.value*b.value, * FROM a, b
PromQL:
a * b
示例2:
SQL:
SELECT a.value * b.value, a.foo, a.bar
FROM a INNER JOIN b ON (a.foo == b.foo AND a.bar == b.bar)
PromQL:
a * on (foo, bar) b
示例3:
SQL:
SELECT a.value * b.value, a.*, b.baz
FROM a JOIN b ON (a.foo == b.foo AND a.bar == b.bar)
PromQL:
a * on (foo, bar) group_left(baz) b
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)