广告
返回顶部
首页 > 资讯 > 数据库 >Prometheus时序数据库中怎么查询数据
  • 879
分享到

Prometheus时序数据库中怎么查询数据

2024-04-02 19:04:59 879人浏览 独家记忆
摘要

今天就跟大家聊聊有关prometheus时序数据库中怎么查询数据,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Promql一个ProMQl表达式可以

今天就跟大家聊聊有关prometheus时序数据库中怎么查询数据,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

Promql

一个ProMQl表达式可以计算为下面四种类型:

瞬时向量(Instant Vector) - 一组同样时间戳的时间序列(取自不同的时间序列,例如不同机器同一时间的CPU idle) 区间向量(Range vector) - 一组在一段时间范围内的时间序列 标量(Scalar) - 一个浮点型的数据值 字符串(String) - 一个简单的字符串

我们还可以在Promql中使用svm/avg等集合表达式,不过只能用在瞬时向量(Instant  Vector)上面。为了阐述Prometheus的聚合计算以及篇幅原因,笔者在本篇文章只详细分析瞬时向量(Instant Vector)的执行过程。

瞬时向量(Instant Vector)

前面说到,瞬时向量是一组拥有同样时间戳的时间序列。但是实际过程中,我们对不同Endpoint采样的时间是不可能精确一致的。所以,Prometheus采取了距离指定时间戳之前最近的数据(Sample)。如下图所示:

Prometheus时序数据库中怎么查询数据

当然,如果是距离当前时间戳1个小时的数据直观看来肯定不能纳入到我们的返回结果里面。

所以Prometheus通过一个指定的时间窗口来过滤数据(通过启动参数—query.lookback-delta指定,默认5min)。

对一条简单的Promql进行分析

好了,解释完Instant Vector概念之后,我们可以着手进行分析了。直接上一条带有聚合函数的Promql吧。

SUM BY (group) (Http_requests{job="api-server",group="production"})

首先,对于这种有语法结构的语句肯定是将其Parse一把,构造成AST树了。调用

promql.ParseExpr

由于Promql较为简单,所以Prometheus直接采用了LL语法分析。在这里直接给出上述Promql的AST树结构。

Prometheus时序数据库中怎么查询数据

Prometheus对于语法树的遍历过程都是通过vistor模式,具体到代码为:

ast.Go vistor设计模式 func Walk(v Visitor, node Node, path []Node) error {     var err error     if v, err = v.Visit(node, path); v == nil || err != nil {         return err     }     path = append(path, node)      for _, e := range Children(node) {         if err := Walk(v, e, path); err != nil {             return err         }     }      _, err = v.Visit(nil, nil)     return err } func (f inspector) Visit(node Node, path []Node) (Visitor, error) {     if err := f(node, path); err != nil {         return nil, err     }      return f, nil }

通过golang里非常方便的函数式功能,直接传递求值函数inspector进行不同情况下的求值。

type inspector func(Node, []Node) error

求值过程

具体的求值过程核心函数为:

func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (Value, storage.Warnings, error) {     ......     querier, warnings, err := ng.populateSeries(ctxPrepare, query.queryable, s)     // 这边拿到对应序列的数据     ......     val, err := evaluator.Eval(s.Expr) // here 聚合计算     ......  }

populateSeries

首先通过populateSeries的计算出VectorSelector Node所对应的series(时间序列)。这里直接给出求值函数

func(node Node, path []Node) error {     ......     querier, err := q.Querier(ctx, timestamp.FromTime(mint), timestamp.FromTime(s.End))     ......     case *VectorSelector:         .......         set, wrn, err = querier.Select(params, n.LabelMatchers...)         ......         n.unexpandedSeriesSet = set     ......     case *MatrixSelector:         ...... } return nil

可以看到这个求值函数,只对VectorSelector/MatrixSelector进行操作,针对我们的Promql也就是只对叶子节点VectorSelector有效。

Prometheus时序数据库中怎么查询数据

select

获取对应数据的核心函数就在querier.Select。我们先来看下qurier是如何得到的.

querier, err := q.Querier(ctx, timestamp.FromTime(mint), timestamp.FromTime(s.End))

根据时间戳范围去生成querier,里面最重要的就是计算出哪些block在这个时间范围内,并将他们附着到querier里面。具体见函数

func (db *DB) Querier(mint, maxt int64) (Querier, error) {     for _, b := range db.blocks {         ......         // 遍历blocks挑选block     }     // 如果maxt>head.mint(即内存中的block),那么也加入到里面querier里面。     if maxt >= db.head.MinTime() {         blocks = append(blocks, &rangeHead{             head: db.head,             mint: mint,             maxt: maxt,         })     }     ...... }

Prometheus时序数据库中怎么查询数据

知道数据在哪些block里面,我们就可以着手进行计算VectorSelector的数据了。

// labelMatchers {job:api-server} {__name__:http_requests} {group:production}  querier.Select(params, n.LabelMatchers...)

有了matchers我们很容易的就能够通过倒排索引取到对应的series。为了篇幅起见,我们假设数据都在headBlock(也就是内存里面)。那么我们对于倒排的计算就如下图所示:

Prometheus时序数据库中怎么查询数据

这样,我们的VectorSelector节点就已经有了最终的数据存储地址信息了,例如图中的memSeries refId=3和4。

Prometheus时序数据库中怎么查询数据


如果想了解在磁盘中的数据寻址,可以详见笔者之前的博客

<<Prometheus时序数据库-磁盘中的存储结构>>

通过populateSeries找到对应的数据,那么我们就可以通过evaluator.Eval获取最终的结果了。计算采用后序遍历,等下层节点返回数据后才开始上层节点的计算。那么很自然的,我们先计算VectorSelector。

func (ev *evaluator) eval(expr Expr) Value {     ......     case *VectorSelector:     // 通过refId拿到对应的Series     checkForSeriesSetExpansion(ev.ctx, e)     // 遍历所有的series     for i, s := range e.series {         // 由于我们这边考虑的是instant query,所以只循环一次         for ts := ev.startTimestamp; ts <= ev.endTimestamp; ts += ev.interval {             // 获取距离ts最近且小于ts的最近的sample             _, v, ok := ev.vectorSelectorSingle(it, e, ts)             if ok {                     if ev.currentSamples < ev.maxSamples {                         // 注意,这边的v对应的原始t被替换成了ts,也就是instant query timeStamp                         ss.Points = append(ss.Points, Point{V: v, T: ts})                         ev.currentSamples++                     } else {                         ev.error(ErrTooManySamples(env))                     }                 }             ......         }     } }

如代码注释中看到,当我们找到一个距离ts最近切小于ts的sample时候,只用这个sample的value,其时间戳则用ts(Instant  Query指定的时间戳)代替。

其中vectorSelectorSingle值得我们观察一下:

func (ev *evaluator) vectorSelectorSingle(it *storage.BufferedSeriesIterator, node *VectorSelector, ts int64) (int64, float64, bool){     ......     // 这一步是获取>=refTime的数据,也就是我们instant query传入的     ok := it.Seek(refTime)     ......         if !ok || t > refTime {          // 由于我们需要的是<=refTime的数据,所以这边回退一格,由于同一memSeries同一时间的数据只有一条,所以回退的数据肯定是<=refTime的         t, v, ok = it.PeekBack(1)         if !ok || t < refTime-durationMilliseconds(LookbackDelta) {             return 0, 0, false         }     } }

就这样,我们找到了series 3和4距离Instant  Query时间最近且小于这个时间的两条记录,并保留了记录的标签。这样,我们就可以在上层进行聚合。

Prometheus时序数据库中怎么查询数据

SUM by聚合

叶子节点VectorSelector得到了对应的数据后,我们就可以对上层节点AggregateExpr进行聚合计算了。代码栈为:

evaluator.rangeEval     |->evaluate.eval.func2         |->evelator.aggregation grouping key为group

具体的函数如下图所示:

func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, param interface{}, vec Vector, enh *EvalNodeHelper) Vector {     ......     // 对所有的sample     for _, s := range vec {         metric := s.Metric         ......         group, ok := result[groupingKey]          // 如果此group不存在,则新加一个group         if !ok {             ......             result[groupingKey] = &groupedAggregation{                 labels:     m, // 在这里我们的m=[group:production]                 value:      s.V,                 mean:       s.V,                 groupCount: 1,             }             ......         }         switch op {         // 这边就是对SUM的最终处理         case SUM:             group.value += s.V         .....         }     }     .....     for _, aggr := range result {         enh.out = append(enh.out, Sample{         Metric: aggr.labels,         Point:  Point{V: aggr.value},         })     }     ......     return enh.out }

好了,有了上面的处理,我们聚合的结果就变为:

Prometheus时序数据库中怎么查询数据

看完上述内容,你们对Prometheus时序数据库中怎么查询数据有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网数据库频道,感谢大家的支持。

您可能感兴趣的文档:

--结束END--

本文标题: Prometheus时序数据库中怎么查询数据

本文链接: https://www.lsjlt.com/news/58014.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Prometheus时序数据库中怎么查询数据
    今天就跟大家聊聊有关Prometheus时序数据库中怎么查询数据,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Promql一个Promql表达式可以...
    99+
    2022-10-18
  • Prometheus时序数据库怎么插入数据
    本篇内容主要讲解“Prometheus时序数据库怎么插入数据”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Prometheus时序数据库怎么插入数据”吧!前言在...
    99+
    2022-10-18
  • 怎么在MySQL数据库中进行时间查询数据
    这篇文章主要介绍“怎么在MySQL数据库中进行时间查询数据”,在日常操作中,相信很多人在怎么在MySQL数据库中进行时间查询数据问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
    99+
    2023-05-25
    mysql
  • Mysql数据库时间查询
    1、查询当前时间  年月日时分秒 select now();   2、查询当前时间 前三小时 的时间点 select subdate(now(),interval 3 hour);   3、查询当前时间  前三天 的时间点 select...
    99+
    2023-09-10
    java sql 开发语言
  • 查询数据(数据库)——简单查询
    目录 1.最简单的查询 (1)查询指定列 (2)查询所有列 (3)查询计算列 (4)为列起别名 (5)使用DISTINCT关键字消除重复元组 2.查询满足条件的元组 (1) 比较大小 (2) 确定范围 (3) 确定集合 (4) 字符匹配 (...
    99+
    2023-10-11
    数据库 sql mysql
  • 查询数据库创建时间
    可以执行存储过程sp_helpdb查询到数据库相关信息:     EXECUTE sp_helpdb "Test" GO Source Code 或者查询view视图sys.databases:     SELEC&#...
    99+
    2016-12-08
    查询数据库创建时间
  • PHP怎么查询数据库数据缓存
    在Web开发中,查询数据库数据是一个常见的操作。对于频繁发生的查询操作,如果每次都向数据库发出请求,就会导致数据库压力增大,页面响应速度变慢,影响用户体验。为了解决这个问题,可以使用缓存技术,将经常查询的数据缓存在缓存服务器中,减轻数据库的...
    99+
    2023-05-14
  • php怎么查询数据库中某年的数据
    PHP是一种可以执行服务器端脚本的编程语言,其广泛应用于开发 Web 应用程序,其中最关键的就是从数据库中查询数据以展示在页面上。如何在PHP中查询某年的数据呢?下面,我们将为您详细介绍。首先,我们需要连接数据库,例如连接MySql数据库,...
    99+
    2023-05-14
    php 数据库
  • php怎么查询数据库并正序排列
    PHP是一门流行的编程语言,被广泛应用于Web应用程序的开发。在Web应用程序中,通常会使用一种以上的数据库来存储和管理数据。PHP中有很多方法可以查询数据库,其中一个方法是正序排列。在本篇文章中,我们将探讨如何使用PHP进行数据库查询正序...
    99+
    2023-05-14
    php 数据库
  • MySql数据库时间序列间隔查询方式
    目录mysql时间序列间隔查询mysql查询指定时间间隔数据mysql时间序列间隔查询 在时间序列处理中,采集到的数据保存在数据表中,采集的频率可能是固定间隔(10秒,1小时或者1天...
    99+
    2022-11-13
  • 数据库怎么查询date类型的数据
    要查询date类型的数据,可以使用以下方法: 使用日期函数进行查询:可以使用日期函数(如YEAR、MONTH、DAY等)来获取特定...
    99+
    2023-10-24
    数据库
  • 数据库怎么使用索引查询数据
    使用索引来查询数据可以提高查询的效率。下面是使用索引查询数据的步骤:1. 创建索引:在数据库表中创建索引,可以是单列索引或者组合索引...
    99+
    2023-08-18
    数据库
  • mysql中同时查询两个数据库中数据的方法
    这篇文章给大家分享的是有关mysql中同时查询两个数据库中数据的方法的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。mysql中同时查询两个数据库中数据的方法:首先打开编辑器sub...
    99+
    2022-10-18
  • MySQL数据库查询中怎么实现多表查询
    今天小编给大家分享一下MySQL数据库查询中怎么实现多表查询的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、多表查询多表查...
    99+
    2023-06-29
  • php 怎么查询一段时间内的数据库
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。php 怎么查询一段时间内的数据库?PHP+MySQL实现对一段时间内每天数据统计优化操作实例在互联网项目中,对项目的数据分析必不可少。通常会统计某一段时间内每天数据...
    99+
    2022-11-04
  • MySQL数据库中怎么查询缓存
    这期内容当中小编将会给大家带来有关MySQL数据库中怎么查询缓存,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、缓存条件,原理MySQL Query Cache是用来缓...
    99+
    2022-10-18
  • Server数据库中怎么优化查询
    Server数据库中怎么优化查询,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。  Server数据库查询优化方法有哪些  1.尽量不要使用...
    99+
    2022-10-18
  • sqlserver中怎么查询数据库大小
    本篇文章给大家分享的是有关sqlserver中怎么查询数据库大小,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。但Insus.NET想到的是,从...
    99+
    2022-10-18
  • oracle怎么查询数据库连接数
    Oracle数据库中可以通过以下两种方式查询数据库连接数:1. 使用SQL语句查询V$SESSION视图:可以使用以下SQL语句查询...
    99+
    2023-09-22
    oracle 数据库
  • 查询数据库中表的创建时间
    1、查询MySQL表的创建时间 -- 查询MySQL数据库表的信息 TABLE_SCHEMA:数据库名,table_name:表名SELECT table_name,create_time FROM information_sche...
    99+
    2023-09-30
    数据库 sql mysql
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作