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 聚合操作符选择决策流程

聚合操作符选择决策流程 需要聚合什么? 总量 → sum 平均值 → avg 极值 → min / max 数量 → count 波动 → stddev / stdvar 排序 → topk / bottomk 分位数 → quantile 决策要点: • 延迟类优先用 quantile • 资源类用 avg + stddev 组合 • 错误数用 sum 聚合总量 • 实例健康用 count 监控

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。