3. PromQL 聚合操作符:sum、avg、min、max、count、stddev、stdvar、topk、bottomk、quantile
聚合操作符是 PromQL 中将一组时间序列合并为单一输出序列的核心工具。在告警复核场景中,聚合操作符用于从大量原始指标中提取有意义的聚合值,从而判断整体系统状态,而非关注单一实例的波动。
3.1 聚合操作符分类与功能对比
PromQL 提供了 10 个标准聚合操作符,按功能可分为四类:
| 类别 | 操作符 | 功能描述 | 告警复核典型场景 |
|---|---|---|---|
| 数值聚合 | sum |
计算所有样本值的总和 | 集群总请求量、总错误数 |
avg |
计算所有样本值的算术平均值 | 平均响应时间、平均 CPU 使用率 | |
count |
统计时间序列的数量 | 存活实例数、健康节点数 | |
| 极值聚合 | min |
返回所有样本值中的最小值 | 最低可用磁盘空间、最慢节点延迟 |
max |
返回所有样本值中的最大值 | 峰值流量、最高内存使用率 | |
| 统计聚合 | stddev |
计算样本值的标准差 | 延迟抖动检测、负载不均衡判断 |
stdvar |
计算样本值的方差 | 性能波动幅度量化 | |
| 排序与分位 | topk |
返回值最大的 K 条时间序列 | Top 5 错误率最高的实例 |
bottomk |
返回值最小的 K 条时间序列 | Bottom 3 剩余内存最低的节点 | |
quantile |
计算样本值的 φ 分位数 (0 ≤ φ ≤ 1) | P99 延迟、P95 错误率 |
复核要点:在告警表达式中,
sum 和 avg 是最常用的聚合操作符,但 stddev 和 quantile 在检测异常波动时往往比平均值更敏感。建议在延迟类告警中优先使用 quantile(0.99, ...) 而非 avg。
3.2 聚合操作符语法与 without / by 子句
所有聚合操作符都支持 without 和 by 子句来控制聚合维度:
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
- by:保留指定的标签维度进行分组聚合,其余标签被丢弃。
- without:移除指定的标签维度,保留其余标签进行分组聚合。
示例对比:
sum by (job) (http_requests_total) — 按 job 分组求和,每个 job 得到一个总和。sum without (instance) (http_requests_total) — 移除 instance 标签,按剩余标签分组求和,常用于聚合所有实例数据。
3.3 聚合操作符在告警复核中的典型用法
3.3.1 sum:总量监控
用于统计集群级别的总请求量、总错误数、总流量等。在告警复核中,sum 常用于判断整体业务量是否异常。
# 集群总错误率超过 5%
sum by (service) (rate(http_requests_total{status=~"5.."}[5m]))
/ sum by (service) (rate(http_requests_total[5m])) > 0.05
3.3.2 avg:平均负载
计算一组实例的平均指标值,适合 CPU 使用率、内存使用率等资源类告警。
# 所有数据库实例的平均 CPU 使用率超过 80%
avg by (cluster) (cpu_usage_percent{role="db"}) > 80
3.3.3 min / max:极端值检测
用于发现集群中的"短板"或"热点"实例。
# 任意实例的磁盘剩余空间低于 10%(min 保留最差情况)
min by (instance) (disk_free_percent) < 10
# 任意实例的内存使用率超过 95%(max 保留最差情况)
max by (instance) (memory_usage_percent) > 95
3.3.4 count:实例数量监控
用于检测实例数量变化,常用于服务发现异常或大规模宕机场景。
# 健康实例数低于预期(预期 3 个)
count by (service) (up{job="api-server"} == 1) < 3
3.3.5 stddev / stdvar:波动检测
标准差和方差用于量化指标波动程度。在告警复核中,stddev 比 avg 更能反映负载不均衡问题。
# 各实例 CPU 使用率的标准差超过 20%,表示负载严重不均衡
stddev by (cluster) (cpu_usage_percent) > 20
3.3.6 topk / bottomk:排序筛选
返回前 K 个或后 K 个极端值序列,常用于定位问题实例。
# 查看错误率最高的 5 个实例(topk 返回多条时间序列)
topk(5, rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]))
注意:
topk 和 bottomk 返回的是多条时间序列,而非单一聚合值。在告警条件中,它们通常与 and 或其他比较操作符配合使用,或直接用于可视化面板而非告警规则。
3.3.7 quantile:分位数分析
分位数是延迟类告警的黄金标准。φ 取值 0.5 表示中位数,0.99 表示 P99 延迟。
# P99 延迟超过 500ms
quantile by (service) (0.99, rate(http_request_duration_seconds_bucket[5m])) > 0.5
3.4 聚合操作符选择决策流程
3.5 聚合操作符在告警表达式中的常见陷阱
| 陷阱 | 错误示例 | 正确做法 | 说明 |
|---|---|---|---|
| 聚合维度丢失 | sum(rate(...)) > 100 |
sum by (service) (rate(...)) > 100 |
不加 by/without 会聚合所有序列为单一值,无法定位具体服务 |
| avg 掩盖极端值 | avg(cpu_usage) > 80 |
max(cpu_usage) > 95 or avg(cpu_usage) > 80 |
平均值可能掩盖个别实例的极端高负载 |
| quantile 误用 φ 值 | quantile(0.5, ...) > 0.5 |
quantile(0.99, ...) > 0.5 |
中位数对长尾延迟不敏感,应使用高百分位 |
| topk 用于告警条件 | topk(5, ...) > 0.1 |
使用 max 或 quantile 替代 |
topk 返回多条序列,比较操作符行为不符合预期 |
| stddev 单独使用 | stddev(cpu_usage) > 20 |
stddev(cpu_usage) > 20 and avg(cpu_usage) > 50 |
标准差需结合平均值才有实际意义 |
3.6 聚合操作符组合使用示例
在实际告警复核中,多个聚合操作符经常组合使用以提升告警准确性:
# 组合示例:检测服务延迟异常且负载不均衡
# 条件1:P99 延迟超过 500ms
# 条件2:各实例延迟标准差超过 100ms(表示不均衡)
(
quantile by (service) (0.99, rate(http_request_duration_seconds_bucket[5m])) > 0.5
)
and
(
stddev by (service) (rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m])) > 0.1
)
复核建议:在编写告警表达式时,建议先使用
sum by (service) 或 avg by (service) 确定整体趋势,再使用 stddev 或 quantile 检测异常分布。这种"总量 + 波动"的组合模式能有效减少误告警。
3.7 聚合操作符与 rate / increase 的配合
在告警表达式中,聚合操作符通常与 rate 或 increase 配合使用,用于计算每秒速率或增量:
# 正确:先 rate 再聚合
sum by (service) (rate(http_requests_total[5m]))
# 错误:先聚合再 rate(语义错误)
rate(sum by (service) (http_requests_total)[5m])
关键规则:聚合操作符应始终应用于
rate / increase 之后,而非之前。先聚合再计算速率会丢失时间维度信息,导致结果语义错误。
3.8 聚合操作符性能考量
| 操作符 | 计算复杂度 | 内存消耗 | 大数据量建议 |
|---|---|---|---|
sum |
O(n) | 低 | 适合百万级序列 |
avg |
O(n) | 低 | 适合百万级序列 |
count |
O(n) | 低 | 适合百万级序列 |
min / max |
O(n) | 低 | 适合百万级序列 |
stddev / stdvar |
O(n) | 中 | 建议控制序列数在 10 万以内 |
topk / bottomk |
O(n log k) | 中 | k 值不宜过大(建议 ≤ 20) |
quantile |
O(n log n) | 高 | 建议配合 histogram 使用,控制 bucket 数量 |
性能优化:在告警复核中,如果指标基数极高(如百万级 pod),建议先通过
by (namespace) 或 by (cluster) 缩小聚合范围,再应用 quantile 或 stddev 等高消耗操作符。对于 quantile,优先使用原生 histogram 指标而非 summary。