TL;DR InfluxDB 技术提示 - 使用 DISTINCT() 和 INTO 子句时数据丢失,使用 MAX() 时时间戳意外以及更多

导航至

当您将函数与 INTO 子句 或 GROUP BY time() 子句结合使用时会发生什么? 有时会出现一些奇怪的结果。在这篇文章中,我们描述了在 SELECT 语句中使用 InfluxQL 函数时遇到的意外情况。

使用 DISTINCT() 和 INTO 子句时数据丢失

问: 我正在尝试将 DISTINCT() 函数的结果写入不同的 measurement。唯一的问题是 - 没有 INTO 子句的查询结果与带有 INTO 子句的查询结果不同。这是预期的行为吗?我觉得我遗漏了什么。

DISTINCT()

> SELECT DISTINCT("personality_type") FROM "twins"

name: twins
time                  distinct
----                  --------
1970-01-01T00:00:00Z  a                 
1970-01-01T00:00:00Z  b                   <--- Three results!
1970-01-01T00:00:00Z  uncategorizable

DISTINCT() 与 INTO

> SELECT DISTINCT("personality_type") INTO "twin_types" FROM "twins"

name: result
time written
---- -------
1970-01-01T00:00:00Z 3      <--- Three written points!

> SELECT * FROM "twin_types"

name: twin_types
time                  distinct
----                  --------
1970-01-01T00:00:00Z  uncategorizable  <--- Just one point!

答: 您看到的行为是预期的行为;这归结于 InfluxDB 如何识别单个 point 以及如何处理重复的 point。

请注意,没有 INTO 子句的 DISTINCT() 查询的每个结果都具有相同的时间戳。InfluxDB 认为同一 series 中且具有相同时间戳的 point 是重复的 point。

当您将 INTO 子句添加到查询中时,InfluxDB 会将三个重复的 point 写入 twin_types measurement。当系统遇到重复的 point 时,它只是用最新的 point 覆盖之前的 point,因此您最终在目标 measurement 中只有一个结果。这有点出乎意料,但这就是您所看到情况的解释。

使用 MAX() 和 GROUP BY time() 子句时时间戳意外

问:  我正在尝试查找特定时间间隔内的 maximum 鸡蛋数量。max 列中的结果是准确的,但 time 列中的时间戳与我预期的不同。我在下面包含了数据的简化版本。为什么时间戳看起来不对劲?

原始数据

> SELECT * FROM "house"

name: house
time                  eggs
----                  ----
2017-04-12T20:00:00Z  1     <--- Max value in the first 20-minute interval
2017-04-12T20:10:00Z  0
2017-04-12T20:20:00Z  3
2017-04-12T20:30:00Z  5     <--- Max value in the second 20-minute interval

我的查询

> SELECT MAX("eggs") FROM "house" WHERE time >= '2017-04-12T20:00:00Z' AND time <= '2017-04-12T20:30:00Z' GROUP BY time(20m)

name: house
time                  max
----                  ---
2017-04-12T20:00:00Z  1
2017-04-12T20:20:00Z  5     <--- I'd expect this timestamp to be 2017-04-12T20:30:00Z

答: 您看到的时间戳是 GROUP BY time() 子句的结果。该子句会自动使用标记相关时间间隔开始的时间戳覆盖 MAX() 的原始时间戳。

在您的情况下,结果中的第二个时间戳 (2017-04-12T20:20:00Z) 指的是 2017-04-12T20:20:00Z2017-04-12T20:30:00Z 之前的时间间隔,而不是原始数据中 maximum 值发生的时间。几乎所有*使用 InfluxQL 函数和 GROUP BY time() 子句的查询都以这种方式覆盖时间戳。

  • 唯一的例外是 SAMPLE() 函数。有关更多信息,请参阅 SAMPLE() 文档

使用 ELAPSED() 和 GROUP BY time() 子句时一致性意外

问:  我正在使用 ELAPSED() 来计算数据中 median 值之间的时间间隔。我得到的结果(见下文)始终显示相同的时间间隔。我很难相信 我的 median 值总是正好相隔十分钟。我是否正确使用了 ELAPSED() 函数?

> SELECT ELAPSED(MEDIAN("clicks"),1m) FROM "puppies" WHERE time >= '2017-04-12T18:30:00Z' AND time <= '2017-04-12T19:10:00Z' GROUP BY time(10m)

name: puppies
time                  elapsed
----                  -------
2017-04-12T18:40:00Z  10
2017-04-12T18:50:00Z  10
2017-04-12T19:00:00Z  10

答: 从语法角度来看,您正确使用了 ELAPSED() 函数,但您的查询不会给您带来您想要的结果。当您将 ELAPSED() 与嵌套函数和 GROUP BY time() 子句一起使用时,InfluxDB 始终返回等于 GROUP BY time() 间隔的 elapsed 值。

当您运行查询时,InfluxDB 首先在指定的 GROUP BY time() 间隔计算嵌套函数 (MEDIAN()) 的结果,然后将 ELAPSED() 函数应用于这些结果。在第一步中,GROUP BY time() 子句会自动使用标记每个 GROUP BY time() 间隔开始的时间戳覆盖 MEDIAN() 的原始时间戳。当系统将 ELAPSED() 函数应用于第一步的结果时,它会遇到始终相隔十分钟的时间戳,而不是 MEDIAN() 值的原始时间戳。

 

下一步

  • 下载 TICK-stack 的下载已在我们的“下载”页面上线。
  • 云端部署: 免费试用 InfluxDB Cloud ,体验完全托管的集群、Kapacitor 和 Grafana。
  • 在您的服务器上部署: 想在您的服务器上运行 InfluxDB 集群?免费试用 14 天 InfluxDB Enterprise ,体验用于部署、监控和重新平衡集群的直观 UI,以及管理备份和恢复。 
  • 讲述您的故事: 超过 300 家公司 分享了 InfluxDB 如何帮助他们成功的案例。提交您的客户评价,即可获得限量版连帽衫,以表感谢。