欢迎参与 8 月 1 日中午 11 点的线上分享,了解 GreptimeDB 联合处理指标和日志的最新方案! 👉🏻 点击加入

Skip to content
On this page
技术
2023-2-10

找 ChatGPT 写 SQL? 不如试试 PromQL,三行解决复杂时序场景查询

PromQL 被广泛认为是云原生可观测性中最常用的查询语言。本文简要分享了 PromQL 的历史和特性,并通过简单示例展示了其相较于 SQL 的优势。

PromQL 的前世今生

PromQL(Prometheus Query Language) 是 Prometheus 监控系统的查询语言,用于对时序数据进行查询,分析和聚合。PromQL 表达能力强大、灵活,可以帮助开发者快速提取和操作时间序列数据,在云原生可观测领域已经是公认使用最广泛的查询语言了。相比 SQL 通用语言,PromQL 是针对时序和监控的领域语言,它的由来值得介绍一下。

早在 2012 年,Julius Volz 和 Matt Proud 在 SoundCloud 的时候共同研发了 Prometheus,PromQL 也随之诞生。但故事并不是从 2012 年才开始的,更早之前 Volz 在 Google 就已经开始了相关工作,对应的是 Borgmon 的查询语言, Borgmon 是 Borg 系统的监控服务,那 Borg 又是什么呢?

可能大家都听过 Kubernetes,Borg 可以说是 K8s 的前身,所以 Borg 对应了 Kubernetes, Borgmon 对应了 Prometheus,而 PromQL 就起源于当年的 Borgmon 查询语言,现在看来 PromQL 从出生就带上来云原生可观测的基因

为什么使用 PromQL

借用互联网前辈的产品方法公式,用户价值 = 新体验 - 旧体验 - 替换成本,SQL 已经非常强大,而且深入人心了,为什么我们还需要花时间再去掌握 PromQL?

PromQL 是一门领域语言,处理的场景是监控场景,面对的数据是时序数据。监控的逻辑是会以时序的形式采集大量系统指标,再对这些指标做聚合、分析和计算,从这些结果中寻找系统的规律,及时探测异常以及定位问题。监控指标有两个关键属性,标签时间,一个指标系列是通过标签整合,比如某台服务器的 CPU 情况,也往往会通过时间来聚合,比如最近 7 天的气温变化,PromQL 就是针对这些数据的选择,计算和分析等常用操作提供了非常友好的语法和函数。

"Talk is cheap, show me the code", 我们就拿一些简单的例子来说明。

PromQL 使用案例

背景

假设现在需要检测城市环境信息,包括温度,湿度,空气质量,噪音,水污染等等数据指标,这些指标已经通过相应的传感器设备采集,并且存储到了合适的时序数据库.

为了简单起见,我们就以温度和噪音两个指标举例,比如温度的指标名字是 city_env_temp_total, 噪音指标名字 city_env_noise_total,如果用的是传统的数据库,我们假设表名就是指标名字,即有两张表 city_env_temp_totalcity_env_noise_total

查询

我们先从一个不实际但最简单的查询开始,查看所有城市所有时间的气温指标,SQL 和 PromQL 语句分别如下:

  • SQL
sql
SELECT * 
FROM city_env_temp_total;
  • PromQL
city_env_temp_total

PromQL 可以直接通过指标名称来获取所有的指标数据,比 SQL 简单了那么一些,那如果我们想要查看某个城市所有时间的气温指标呢

  • SQL
sql
SELECT * 
FROM city_env_temp_total 
WHERE city = "hangzhou";
  • PromQL
city_env_temp_total{city="hangzhou"}

PromQL 可以通过 {} 来做条件过滤和匹配,与 SQL 的 where 类似,而且还支持正则表达,主要是:

  • = : 选择与查询内容完全匹配的数据

  • != : 选择与查询内容不同的数据

  • =~ : 按照正则,选择与查询内容匹配的数据

  • !~ : 按照正则,选择与查询内容不同的数据

比如我们要查询多个城市的气温数据

  • SQL
sql
SELECT * 
FROM city_env_temp_total 
WHERE city = "hangzhou" OR city = "beijing" OR city = "shanghai";
  • PromQL
sql
city_env_temp_total{city=~"hangzhou|beijing|shanghai"}

而实际情况,我们不会把所有时间的环境指标都拿出来分析,往往是会看最近一段时间, 比如最近一个月或最近一年:

sql
SELECT * 
FROM city_env_temp_total 
Where city = "hangzhou" and data >= (CURDATE() - INTERVAL 1 MONTH )
  • PromQL
city_env_temp_total{city="hangzhou"}[30d]

PromQL 通过 [] 来做区间查询,支持的时间单位如下:

  • ms - milliseconds

  • s - seconds

  • m - minutes

  • h - hours

  • d - days - 假设一天是 24 小时

  • w - weeks - 假设一周 7 天

  • y - years - 假设一年 365 天

PromQL 还提供了其他的操作符来简化查询,比如 offset 等,就不详细展开了,有兴趣的朋友可以查看官方手册 range-vector-selectors

计算

PromQL 还提供了大量用于计算的函数,比如

  • sum() 求和

  • min() 最小值

  • max() 最大值

  • avg() 平均值

  • rate() 时间窗口内每秒的平均增长率

具体可以参看: https://prometheus.io/docs/prometheus/latest/querying/functions/

比如我们想查询过去一个月每天平均噪音大于 100 dB 的城市数据

  • SQL:
sql
SELECT city, AVG(noise) as avg_noise
FROM city_env_noise_total
GROUP BY city, DATE(timestamp)
HAVING AVG(noise) > 100;
  • PromQL
avg_over_time(city_env_noise_total[30d]) > 100

我们可以尝试一个更复杂的例子,查看过去一个月内每个城市的平均噪音情况,在其中筛选出平均噪音超过 100 分贝至少有 15 天的城市

  • SQL (由于实在是太复杂了,本人只能用 ChatGPT 生成这个 SQL)
sql
SELECT city,
       (SUM(CASE WHEN avg_noise > 100 THEN 1 ELSE 0 END) / 30) > 0.5 as above_threshold
FROM (
  SELECT city, AVG(noise) as avg_noise
  FROM city_env_noise_total
  WHERE timestamp >= NOW() - INTERVAL 1 MONTH
  GROUP BY city
) data
GROUP BY city
  • PromQL
sum(
  avg_over_time(city_env_noise_total[30d]) > bool 100
) by (city) / 30 > 0.5

相信通过上面的例子,相信足以看出 PromQL 在查询分析时序数据领域强大的表达能力。相比 SQL 的通用性来讲,PromQL 还是有它的局限性,比如 join 查询等。但是,PromQL 毕竟是一门领域语言,在不同的场景下选择最合适的语言才是最佳的办法。

结语

有个笑话是“很多很多年以后,也许 Prometheus 这个商业公司都不存在,但 PromQL 一定还会以他的方式流传下去”,作为从业者,由衷感谢 Prometheus 社区为时序领域带来了这么棒的查询语言。

这些年 PromQL 社区依然非常活跃,在聚合函数,查询性能方面优化了很多,也有很多开发者在 PromQL 的基础上扩展了新的语法,可以说 PromQL 已经成为 Cloud-Native 下对时序数据操作必须要支持的标准语言了

GreptimeDB 也会在 0.1 版本的发布中初步支持 PromQL,希望可以给用户带来真正的价值,届时欢迎试用反馈!

关于 Greptime

Greptime 格睿科技专注于为可观测、物联网及车联网等领域提供实时、高效的数据存储和分析服务,帮助客户挖掘数据的深层价值。目前基于云原生的时序数据库 GreptimeDB 已经衍生出多款适合不同用户的解决方案,更多信息或 demo 展示请联系下方小助手(微信号:greptime)。

欢迎对开源感兴趣的朋友们参与贡献和讨论,从带有 good first issue 标签的 issue 开始你的开源之旅吧~期待在开源社群里遇见你!添加小助手微信即可加入“技术交流群”与志同道合的朋友们面对面交流哦~

Star us on GitHub Now: https://github.com/GreptimeTeam/greptimedb

官网:https://greptime.cn/

文档:https://docs.greptime.cn/

Twitter: https://twitter.com/Greptime

Slack: https://greptime.com/slack

LinkedIn: https://www.linkedin.com/company/greptime/

加入我们的社区

获取 Greptime 最新更新,并与其他用户讨论。