首页 > 解决方案 > InfluxDB - 保持下采样记录的时间戳

问题描述

使用的 InfluxDB 版本:1.8.0

给定一个时间序列数据库,用于存储来自物联网传感器(在不同位置)的温度。
例如每隔一分钟查询传感器。
现在可以使用查询过去一小时每个传感器的最高温度

   select max(*) from temperatures where time >= now() - 1h group by location 
   name: temperatures
   tags: location=collector
   time                 max_temperature
   ----                 ---------------
   2020-06-24T17:41:34Z 34.8
   
   name: temperatures
   tags: location=outside
   time                 max_temperature
   ----                 ---------------
   2020-06-24T17:43:34Z 23.4

我现在想在一段时间内保持每小时和每天的最高温度。
所以很自然我会使用保留策略和持续查询。

假设我想按小时存储一个月的最高温度:

   show RETENTION POLICIES on iotsensors
   name       duration   shardGroupDuration replicaN default
   ----       --------   ------------------ -------- -------
   lastmonth  744h0m0s   24h0m0s            1        false

连续查询如下所示:

   CREATE CONTINUOUS QUERY max_temperatures_per_hour ON iotsensors 
   BEGIN 
     SELECT max(temperature) INTO iotsensors.lastmonth.max_temperatures_per_hour FROM iotsensors.autogen.temperatures GROUP BY time(1h), location TZ('Europe/Berlin') 
   END

根据GROUP BY time(1h)术语的性质,温度的准确时间会丢失。
尤其是当数据在第二步浓缩一整天时,FROM iotsensors.lastmonth.max_temperatures_per_hour GROUP BY time(1d)分辨率变得更加粗糙。(设置为每天的午夜00:00:00

   select max from iotmeasurements.last2years.max_temperatures_per_day where time >= now() - 4d group by location tz('Europe/Berlin')

   name: max_temperatures_per_day
   tags: location=collector
   time                      max
   ----                      ---
   2020-06-21T00:00:00+02:00 80.9
   2020-06-22T00:00:00+02:00 78.5
   2020-06-23T00:00:00+02:00 101.2

   name: min_max_temperatures_per_day
   tags: location=outside
   time                      max
   ----                      ---
   2020-06-21T00:00:00+02:00 21.8
   2020-06-22T00:00:00+02:00 22.5
   2020-06-23T00:00:00+02:00 22.8

我知道这是预期和记录的行为
https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/#group-by-time-intervals

但是,关于何时准确记录最大值的信息是我想保留的有价值的信息。

有没有办法在下采样时存储记录的确切时间戳?
我更愿意将时间戳保留在时间字段中,例如

   tags: location=collector
   time                 max
   ----                 ---
   2020-06-20T04:30:40Z 80.9
   2020-06-21T04:22:00Z 78.5
   2020-06-22T04:53:10Z 101.2

或者,第二个最佳解决方案是为每个下采样记录添加一个时间戳字段

   time                      max    timestamp
   ----                      ---    ---------
   2020-06-20T00:00:00+02:00 80.9   2020-06-20T04:30:40Z
   2020-06-21T00:00:00+02:00 78.5   2020-06-21T04:22:00Z
   2020-06-22T00:00:00+02:00 101.2  2020-06-22T04:53:10Z

为此,我需要能够将时间查询到一个单独的字段中,不是吗。
但到目前为止我的尝试并不成功。我试过的是这样的:

SELECT max(temperature),time as timestamp FROM temperatures GROUP BY time(60m),"location"

如果这是解决我的问题的先决条件,我会考虑迁移到 InfluxDB 2.0。

标签: influxdbdownsampling

解决方案


到目前为止,我还没有找到仅使用 InfluxDB 的解决方案。
最初的问题是基于这样一种误解,即在用于下采样的时间范围内始终存在一个最大值。给定一系列这样的数据点。

   name: max_temperatures_per_day
   tags: location=collector
   time                      max
   ----                      ---
   2020-06-20T04:30:40Z 80.9
   2020-06-21T04:22:00Z 78.5
   2020-06-22T04:53:10Z 101.2
   2020-06-22T05:33:10Z 73.3
   2020-06-22T05:41:10Z 65.0
   2020-06-22T05:53:10Z 48.2
   2020-06-22T05:56:10Z 73.3
   2020-06-22T10:30:10Z 54.3
   2020-06-22T12:30:10Z 63.7
   2020-06-22T18:03:10Z 101.2
   2020-06-22T18:20:10Z 90.2

可以在一天中的第 4 个小时准确地确定一个具有最大值的时间点,2020-06-22T04:53:10Z 101.2但在第 5 个小时,这是不可能的,因为最大值出现在 5:33 和 5:56。将数据下采样到一天 (24 小时) 的分辨率会使情况变得更糟,因为最大值 (101.2) 出现在当天上午 4 点 53 分和下午 6 点 03 分。应该保留这可能的多个时间点中的哪一个?

然而,使用 Kapacitor 执行持续查询,可以实现原始所需的结果。从这篇文章https://docs.influxdata.com/kapacitor/v1.5/guides/continuous_queries/开始,可以设置这样的查询


batch
  |query('SELECT * FROM "iotmeasurements"."autogen".temperatures')
    .period(1h)
    .every(1h)
    .groupBy('location')
    .align()
  |max('temperature')
    .as('max_temp')
    .usePointTimes()
  |influxDBOut()
    .database('iotmeasurements')
    .retentionPolicy('lastmonth')
    .measurement('max_temperatures')
    .precision('s')

这将保持最大值首先出现的时间点。在下面的示例中,将保留上午 5:33 的数据点,并跳过上午 5:56 的相同值。
我不完全确定是否需要usePointTimes()https://docs.influxdata.com/kapacitor/v1.5/nodes/influx_q_l_node/#usepointtimes)。

如果在下采样时间范围内丢失最大值的后续出现记录是可以接受的,这可能是一个解决方案。尽管如此,为此需要运行第二个服务。添加一个额外的可能的故障转移点。使用 Kapacitor 的另一个缺点是似乎无法对过去执行下采样。
可以在连续查询之外执行GROUP BY time这样SELECT max(temperature) INTO ... FROM temperatures WHERE time >= now() - 1w GROUP BY time(1h),"location"的查询,以对 influxdb 本身内部过去的测量点进行下采样。
现在似乎有办法让 Kapacitor 'ticks' 这样做。


推荐阅读