PromQL语法

PromQL 语法知识

最后更新时间:2026年1月7日
适用对象:Prometheus 初学者、运维工程师、SRE、DevOps 工程师
目标:系统掌握 PromQL 核心语法、数据模型、函数、操作符及最佳实践


目录


一、PromQL 简介

PromQL(Prometheus Query Language)是 Prometheus 内置的函数式查询语言,用于:

  • 实时筛选和聚合时间序列数据
  • 构建监控图表(Grafana)
  • 定义告警规则(Alertmanager)
  • 分析系统性能瓶颈

一句话理解
PromQL = 从「带标签的时间序列」中筛选、计算、聚合数据的语言

查询流程

graph LR A[输入查询] --> B[语法解析] B --> C[标签匹配器筛选时间序列] C --> D[执行函数/聚合/计算] D --> E[返回结果]

PromQL ≠ SQL

对比项 SQL PromQL
操作对象 表、行 时间序列(指标 + 标签)
核心维度 时间 + 标签
查询结果 静态结果集 随时间变化的向量
数据模型 关系型 多维时间序列

二、Prometheus 数据模型

每条时间序列由以下三部分唯一标识:

<metric_name>{<label_name>=<label_value>, ...} @timestamp → value

示例

http_requests_total{method="POST", handler="/api", status="200", instance="10.0.0.91:9100"} 1625097600 → 1500
↑                     ↑    ↑                        ↑     ↑                                ↑           ↑
指标名称               标签名  标签值                  标签名   标签值                          时间戳         值
  • 指标名(Metric Name):如 node_cpu_seconds_total
  • 标签(Labels):键值对,用于多维切片(如 job, instance, status
  • 样本(Sample)(timestamp, value) 数据点

💡 本质:PromQL 是对一堆带标签的时间序列做过滤、计算、聚合。


三、PromQL 四种数据类型

类型 说明 示例 特点
瞬时向量(Instant Vector) 某一时刻的多个时间序列 node_cpu_seconds_total 多条序列 + 单值(最新值)
区间向量(Range Vector) 一段时间内的多个时间序列 node_cpu_seconds_total[5m] 多条序列 + 多值(历史窗口)
标量(Scalar) 单一数值 3.14 无时间戳,可参与计算
字符串(String) 字符串字面量 "hello" 仅用于标签,几乎不用

重要:写 PromQL 前,必须清楚当前表达式返回的是什么类型!


四、时间序列选择器

4.1 瞬时向量选择器

返回当前时间点的最新样本值。

基本语法

metric_name{label_key="value", ...}

示例

# 所有 http_requests_total 指标
http_requests_total

# 过滤 job="api-server"
http_requests_total{job="api-server"}

# 多标签精确匹配
http_requests_total{method="GET", status="200"}

# 排除特定值
http_requests_total{method!="GET"}

# 正则匹配(支持 RE2 语法)
node_cpu_seconds_total{instance=~"prod-.*"}
http_requests_total{version=~"v1\\..*"}

# 排除正则匹配
http_requests_total{env!~"test|dev"}

# 查找空标签
http_requests_total{instance=""}

# 转义特殊字符(如 .)
{host=~"web\\d+\\.example\\.com"}

4.2 区间向量选择器

返回过去一段时间内的所有样本值,必须配合函数使用

语法

metric_name[<duration>]

时间单位

单位 含义
ms 毫秒
s
m 分钟
h 小时
d
w
y

⚠️ 注意

  • 必须使用整数(如 5m,不能 1.5h
  • 可组合(如 1h30m),但顺序必须从大到小

示例

# 过去 5 分钟所有样本
http_requests_total[5m]

# 过去 1 小时请求耗时
http_request_duration_seconds[1h]

# ❌ 错误:区间向量不能直接显示
http_requests_total[5m]  # 无效!
# ✅ 正确:必须搭配函数
rate(http_requests_total[5m])

4.3 偏移修饰符(offset)

调整查询的基准时间点,用于对比历史数据。

语法

<selector> offset <duration>

示例

# 查询 1 天前的当前值
http_requests_total offset 1d

# 查询 1 小时前的 5 分钟速率
rate(http_requests_total[5m] offset 1h)

# 对比今日 vs 昨日流量
rate(http_requests_total[1h]) / rate(http_requests_total[1h] offset 1d)

五、标签匹配器(Label Matchers)

用于在选择器中过滤时间序列。

操作符 含义 示例
= 精确匹配 {job="api"}
!= 不等于 {status!="500"}
=~ 正则匹配 {instance=~"prod-.*"}
!~ 正则不匹配 `{env!~"test

🔍 正则引擎:基于 RE2,不支持向前断言(lookahead)等高级特性。


六、PromQL 操作符

6.1 算术操作符

操作符 说明
+ - * / % ^ 加减乘除、取模、幂运算

示例

# 计算错误率
rate(http_requests_total{status="500"}[5m]) / rate(http_requests_total[5m])

# 内存使用百分比
(node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes * 100

# 转换为比特率
rate(node_network_receive_bytes_total[2m]) * 8

6.2 比较操作符

操作符 说明
== != 等于、不等于
> < >= <= 大于、小于等
== bool != bool 返回布尔值(0 或 1)

示例

# 返回值 > 100 的时间序列
node_filesystem_avail_bytes > 100

# 返回布尔结果(用于过滤)
node_filesystem_avail_bytes > bool 100

# 筛选内存不足 100MB 的节点
node_memory_free_bytes < 100 * 1024^2

6.3 逻辑/集合操作符

操作符 说明
and 交集(保留两边都存在的序列)
or 并集(合并序列)
unless 差集(左边存在但右边不存在)

示例

# 保留 job="api" 且 status="500" 的序列
http_requests_total{job="api"} and http_requests_total{status="500"}

# 合并两个指标
http_requests_total{job="api"} or http_requests_total{job="frontend"}

# 排除特定实例
http_requests_total unless http_requests_total{instance="backup"}

6.4 操作符优先级(从高到低)

^
*, /, %
+, -
==, !=, <=, <, >=, >
and, unless
or

💡 建议使用括号 () 明确优先级,避免歧义。


七、核心内置函数

7.1 速率与增量函数(Counter 专用)

函数 用途 示例
rate(v range) 计算每秒平均增长率(平滑) rate(http_requests_total[5m])
irate(v range) 计算瞬时增长率(敏感) irate(http_requests_total[5m])
increase(v range) 计算总增量 increase(http_requests_total[1h])

📌 生产建议

  • 告警用 rate()(平滑,抗抖动)
  • 瞬时监控用 irate()(检测峰值)
  • 区间至少是抓取间隔的 4 倍(如 scrape_interval=15s → range ≥ 1m)

7.2 变化量函数(Gauge 专用)

函数 用途 示例
delta(v range) 绝对变化量(首尾差值) delta(memory_usage_bytes[5m])
idelta(v range) 最后两个点的差值 idelta(cpu_temp[1m])

应用场景

# 内存是否持续上涨
delta(container_memory_usage_bytes[10m]) > 0

# 队列积压变化
delta(queue_length[5m])  # 正数:积压增加;负数:消费更快

7.3 时间窗口聚合函数(_over_time)

对区间向量进行统计。

函数 说明
avg_over_time(v) 平均值
min_over_time(v) 最小值
max_over_time(v) 最大值
sum_over_time(v) 总和
count_over_time(v) 样本数
quantile_over_time(φ, v) 分位数

示例

# 过去 1 小时内存可用量的平均值
avg_over_time(node_memory_free_bytes[1h])

# 过去 30 分钟磁盘 IO 最大值
max_over_time(disk_io_ops[30m])

7.4 预测与趋势函数

函数 用途 示例
predict_linear(v, s) 线性预测未来值 predict_linear(node_filesystem_free_bytes[1h], 6*3600) < 0

✅ 用于磁盘、内存等资源耗尽预警。


7.5 聚合与排序函数

函数 说明
sum(v) 求和
avg(v) 平均值
min(v)/max(v) 最小/最大值
count(v) 计数
topk(k, v) 前 k 个最大值
bottomk(k, v) 前 k 个最小值
sort(v) 升序排序
sort_desc(v) 降序排序

八、聚合操作(Aggregation Operators)

8.1 聚合函数列表

  • sum:求和
  • min:最小值
  • max:最大值
  • avg:平均值
  • stddev:标准差
  • stdvar:方差
  • count:元素个数
  • count_values:等于某值的元素个数
  • bottomk:最小的 k 个元素
  • topk:最大的 k 个元素
  • quantile:分位数

8.2 bywithout 子句

子句 作用
by (label1, label2) 仅保留指定标签进行聚合
without (label1) 移除指定标签后聚合

语法格式(两种等价写法)

<agg>(vector) by (labels)
<agg> by (labels) (vector)

8.3 实战示例

# 按 job 聚合请求总数
sum by (job) (rate(http_requests_total[5m]))

# 排除 instance 标签后取最大值
max without(instance) (cpu_usage)

# 统计不同状态码的数量
count by(status_code) (http_requests_total)

# 获取每个 job 中 CPU 使用最高的实例
topk by(job) (1, rate(container_cpu_usage_seconds_total[1m]))

九、高级技巧

9.1 子查询(Subquery)

在时间范围内以固定间隔执行瞬时查询。

语法

<instant_query>[<range>:<resolution>]

示例

# 计算过去 1 小时内每 5 分钟速率的最大值
max_over_time( rate(http_requests_total[5m])[1h:5m] )

⚠️ 注意:子查询性能开销大,慎用!


9.2 条件表达式(布尔过滤)

结合 bool 和逻辑操作符实现复杂过滤。

# 错误率 > 5% 且总请求 > 100
(
  sum(rate(http_requests_total{status=~"5.."}[5m])) 
  / 
  sum(rate(http_requests_total[5m]))
) > bool 0.05
and
sum(rate(http_requests_total[5m])) > 100

十、指标类型与函数匹配

10.1 Counter(计数器)

  • 特性:只增不减(重启归零)
  • 适用函数rate(), irate(), increase()
  • 典型指标http_requests_total, node_cpu_seconds_total

10.2 Gauge(仪表盘)

  • 特性:可增可减
  • 适用函数delta(), predict_linear()
  • 典型指标node_memory_MemFree_bytes, node_load1

10.3 Histogram(直方图)

  • 生成指标
    • xxx_bucket{le="..."}:累积计数
    • xxx_sum:总和
    • xxx_count:总数
  • 核心函数histogram_quantile(φ, xxx_bucket)
  • 示例
    # P95 延迟
    histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
    

10.4 Summary(摘要)

  • 客户端计算分位数,服务端直接抓取
  • 不推荐(无法跨实例聚合)
  • 优先用 Histogram

十一、经典场景示例

1. CPU 使用率

100 - (
  avg by(instance) (
    rate(node_cpu_seconds_total{mode="idle"}[5m])
  ) * 100
)

2. HTTP 错误率

sum(rate(http_requests_total{status=~"5.."}[5m])) 
/ 
sum(rate(http_requests_total[5m]))

3. 内存不足预警

node_filesystem_free_bytes{mountpoint="/"} 
/ 
node_filesystem_size_bytes{mountpoint="/"} < 0.2

4. 磁盘 6 小时后满载预测

predict_linear(node_filesystem_free_bytes[1h], 6*3600) < 0

十二、避坑指南与最佳实践

问题 解决方案
http_requests_total[5m] 无效 ✅ 必须搭配函数:rate(http_requests_total[5m])
❌ 全量扫描(无标签过滤) ✅ 先用标签缩小范围:{cluster="prod"}
❌ Counter 重置导致负值 ✅ 使用 rate()/increase() 自动处理
❌ 区间太短(< 2×scrape_interval) ✅ 至少 4 倍抓取间隔(如 1m for 15s)
❌ 混淆 rate()irate() ✅ 告警用 rate(),瞬时监控用 irate()
❌ 在 Summary 上计算分位数 ✅ 改用 Histogram + histogram_quantile()

💡 Grafana 提示:在 Explore 模式中实时验证查询,结合 Time Range 和 Step 调整精度。


十三、官方资源推荐


结语:PromQL 是云原生可观测性的核心技能。掌握其数据模型、函数与聚合机制,你将能从容应对任何监控与告警场景。

posted @ 2026-01-07 18:37  ShiLiCoder  阅读(60)  评论(0)    收藏  举报