4. PromQL 基础语法:即时向量与范围向量、选择器与偏移量

PromQL(Prometheus Query Language)是 Prometheus 内置的数据查询语言,用于对时序数据进行实时聚合与分析。理解其核心概念——即时向量、范围向量、选择器以及偏移量——是编写精准查询的基础。本章将逐一拆解这些语法要素,并通过对比表格与流程图帮助建立直观认知。

4.1 即时向量与范围向量

PromQL 查询返回的数据类型分为两种:即时向量(Instant Vector)和范围向量(Range Vector)。两者的核心区别在于:时间维度上的采样点数量。

特性 即时向量 范围向量
定义 每个时间序列在当前时刻的一个最新样本值 每个时间序列在过去一段时间窗口内的一组样本值
语法示例 http_requests_total http_requests_total[5m]
返回结构 一组标签 + 一个浮点值 一组标签 + 一个时间戳-值对数组
典型用途 当前状态、告警规则、瞬时聚合 速率计算(rate/irate)、趋势分析、分位数
是否可直接用于聚合 是(如 sum()、avg()) 否,需先通过函数转换为即时向量
关键理解: 即时向量是“快照”,范围向量是“片段”。在误差预算计算中,rate() 函数必须接收范围向量作为输入,才能计算每秒增长率。

4.2 选择器:精确匹配与正则过滤

选择器用于从指标中筛选出特定的时间序列。PromQL 支持四种标签匹配操作符,覆盖从精确匹配到正则排除的全部场景。

操作符 含义 示例 说明
= 精确相等 job="api-server" 标签值必须完全匹配
!= 精确不相等 job!="api-server" 排除指定标签值
=~ 正则匹配 job=~"api-.*" 标签值匹配正则表达式
!~ 正则排除 job!~"api-.*" 标签值不匹配正则表达式
实战建议: 在误差预算查询中,常用 =~ 批量选择一组微服务(如 service=~"user-.*"),用 != 排除健康检查端点(如 path!="/healthz")。

4.3 偏移量(offset)

offset 修饰符允许查询过去某个时间点的数据,而非当前时间。其语法为在查询表达式后追加 offset <duration>。

  • 基本用法: http_requests_total{job="api"} offset 1h —— 返回 1 小时前的数据。
  • 与范围向量结合: rate(http_requests_total[5m] offset 1h) —— 计算 1 小时前那 5 分钟窗口内的速率。
  • 负偏移(Prometheus 2.28+): http_requests_total offset -5m —— 查询未来 5 分钟的数据(仅用于特殊场景,如预测)。
注意: offset 不会改变时间窗口的长度,只改变窗口的起始位置。在误差预算对比(如本周 vs 上周)中,offset 7d 是标准用法。

4.4 综合示例:误差预算中的选择器与偏移量

假设我们有一个 SLO 指标 http_request_duration_seconds_bucket,需要计算过去 7 天的错误预算消耗率,并与上周同期对比:

# 当前周的错误率(过去 7 天)
rate(http_request_duration_seconds_count{job="api", le="+Inf"}[7d])

# 上周同期的错误率(偏移 7 天)
rate(http_request_duration_seconds_count{job="api", le="+Inf"}[7d] offset 7d)

# 排除特定路径的精确错误率
rate(http_request_duration_seconds_count{job="api", path!~"/healthz|/metrics", le="+Inf"}[5m])

4.5 即时向量 vs 范围向量:选择决策流程

下面的 SVG 流程图展示了在编写 PromQL 时,如何根据查询目标选择正确的向量类型。

即时向量与范围向量选择决策流程 选择即时向量还是范围向量? 查询目标是什么? 需要当前最新值? (告警、仪表盘、瞬时聚合) 需要一段时间窗口? (速率、趋势、分位数) 使用即时向量 例:http_requests_total 使用范围向量 例:http_requests_total[5m] 💡 核心原则 需要计算 rate/irate/histogram_quantile 时,必须使用范围向量

4.6 选择器与偏移量组合:时间旅行查询

下面的 SVG 图展示了 offset 如何与选择器协同工作,实现“时间旅行”式的对比查询。

选择器与偏移量组合查询示意图 选择器 + 偏移量:本周 vs 上周对比 时间轴(现在为 t=0) 现在 5m 5m offset 7d 查询语句对比 本周:rate(http_requests_total{job="api"}[5m]) 上周:rate(http_requests_total{job="api"}[5m] offset 7d)

4.7 常见错误与避坑指南

  • 错误: 对即时向量使用 rate() —— rate(http_requests_total) 会报错,必须改为 rate(http_requests_total[5m])。
  • 错误: 范围向量窗口过大导致性能问题 —— 在误差预算查询中,[30d] 可能返回数百万个样本,建议使用 [7d] 或 [1h] 配合 offset。
  • 错误: 正则选择器未锚定 —— job=~"api" 会匹配任何包含 "api" 的字符串(如 "my-api-v2"),应使用 job=~"^api$" 或 job="api" 进行精确匹配。
  • 错误: 偏移量用于聚合函数内部 —— sum(rate(http_requests_total[5m])) offset 1h 是合法的,但 sum(rate(http_requests_total[5m] offset 1h)) 语义不同,需根据需求选择。
最佳实践: 在编写误差预算 PromQL 时,始终先确定需要的是“当前值”还是“窗口速率”,再选择向量类型。使用 offset 进行同比对比时,确保偏移量与窗口长度匹配业务周期(如 7 天、24 小时)。