InfluxDB时序数据库的安装使用教程5(连续查询CQ)
五、连续查询
1,基本介绍
连续查询 Continuous Query(CQ)是在数据库内部自动周期性跑着的一个 InfluxQL 的查询,InfluxDB 会将查询结果放在指定的数据表中。CQs 需要在 SELECT 语句中使用一个函数,并且一定包括一个 GROUP BY time() 语句。
(1)CQ 的目的:
- 使用连续查询是最优的降低采样率的方式,连续查询和存储策略搭配使用将会大大降低 InfluxDB 的系统占用量。而且使用连续查询后,数据会存放到指定的数据表中,这样就为以后统计不同精度的数据提供了方便。
- 采样和数据保留:使用 CQ 与 InfluxDB 的保留策略(RP)来减轻存储问题。结合 CQ 和 RP 自动将高精度数据降低到较低的精度,并从数据库中移除可分配的高精度数据。
- 预先计算昂贵的查询:通过使用 CQ 预先计算昂贵的查询来缩短查询运行时间。使用 CQ 自动将普通查询的高精度数据下采样到较低的精度。较低精度数据的查询需要更少的资源并且返回更快。
- 替换 HAVING 子句:InfluxQL 不支持 HAVING 子句。通过创建 CQ 来聚合数据并查询 CQ 结果以达到应用 HAVING 子句相同的功能。
- 替换嵌套函数:一些 InfluxQL 函数支持嵌套其他函数,大多数是不行的。如果函数不支持嵌套,可以使用 CQ 获得相同的功能来计算最内部的函数。然后简单地查询 CQ 结果来计算最外层的函数。
2,创建 CQ(基本语法)
(1)我们执行如下命令创建一个 CQ:- 我们创建了一个叫做 cq_30m 的 CQ 作用于 mydb 数据库上
- cq_30m 告诉 InfluxDB 每 30 分钟计算一次 measurement 为 temperature 并使用默认 RP 的字段 internal 和 external 的平均值,然后把结果写入到使用默认 RP,两个字段分别是 mean_internal 和 mean_external 的 measurement 名为 average_temperature 的数据中。
- InfluxDB 会每隔 30 分钟对之前 30 分钟的数据跑一次这个查询。
注意:在 WHERE 子句中,cq_query 不需要时间范围。 InfluxDB 在执行 CQ 时自动生成 cq_query 的时间范围。cq_query 的 WHERE 子句中的任何用户指定的时间范围将被系统忽略。
CREATE CONTINUOUS QUERY "cq_30m" ON "mydb" BEGIN SELECT mean("internal") AS "mean_internal",mean("external") AS "mean_external" INTO "average_temperature" FROM "temperature" GROUP BY time(30m) END
(2)下面是其他一些样例:
// 自动采样数据到另一个保留策略里 CREATE CONTINUOUS QUERY "cq_basic_rp" ON "mydb" BEGIN SELECT mean("external") INTO "mydb2"."three_weeks"."average_external" FROM "temperature" GROUP BY time(1h) END // 使用逆向引用自动采样数据 CREATE CONTINUOUS QUERY "cq_basic_br" ON "mydb" BEGIN SELECT mean(*) INTO "mydb2"."autogen".:MEASUREMENT FROM /.*/ GROUP BY time(30m),* END // 自动采样数据并配置CQ的时间边界 CREATE CONTINUOUS QUERY "cq_basic_offset" ON "mydb" BEGIN SELECT mean("external") INTO "average_external" FROM "temperature" GROUP BY time(1h,15m) END
3,创建 CQ(高级语法)
(1)InfluxDB 连续查询的高级语法如下,与基本语法不同的是,多了 RESAMPLE 关键字。高级语法里 CQ 的执行时间和查询时间范围则与 RESAMPLE 里面的两个 interval 有关系。
CREATE CONTINUOUS QUERY <cq_name> ON <database_name> RESAMPLE EVERY <interval> FOR <interval> BEGIN <cq_query> END
(2)假设我们 bus_data 表中的数据如下:
(3)当我们使用高级语法创建 CQ 只配置执行时间间隔(RESAMPLE EVERY)时:
- 这里配置了 30 分钟执行一次 CQ,没有指定 FOR interval,于是查询的时间范围还是 GROUP BY time(1h) 指定的一个小时。
CREATE CONTINUOUS QUERY "cq_advanced_every" ON "transportation" RESAMPLE EVERY 30m BEGIN SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(1h) END
- 执行流程如下,可以看到这里的 8 点到 9 点这个区间执行了两次,第一次执行时间是 8:30,平均值是 (8+15+15)/ 3 = 12.6667,而第二次执行时间是 9:00,平均值是 (8+15+15+17) / 4=13.75,而且最后第二个结果覆盖了第一个结果。
- 最终的结果如下:
(4)当我们使用高级语法创建 CQ 只配置查询时间范围(RESAMPLE FOR)时:
CREATE CONTINUOUS QUERY "cq_advanced_for" ON "transportation" RESAMPLE FOR 1h BEGIN SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(30m) END
- 因为只配置了时间范围,而没有配置 EVERY interval。这样,执行的时间间隔与 GROUP BY time(30m) 一样为 30 分钟,而查询的时间范围为 1 小时,由于是按 30 分钟分组,所以每次会写入两条记录。
- 需要注意的是,cq_advanced_for 每次写入了两条记录,重复的记录会被覆盖。最终结果如下:
(5)当然我们也可以同时配置执行时间间隔和查询时间范围:
CREATE CONTINUOUS QUERY "cq_advanced_every_for" ON "transportation" RESAMPLE EVERY 1h FOR 90m BEGIN SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(30m) END
- 这里配置了执行间隔为 1 小时,而查询范围 90 分钟,最后分组是 30 分钟,每次插入了三条记录。执行流程如下:
- 同样重复的记录会被覆盖,最终结果如下:
4,显示所有已存在的 CQ
执行如下命令可以显示所有已存在的连续查询(会按照 database 作分组)
SHOW CONTINUOUS QUERIES
5,删除 CQ
执行如下命令删除指定的 CQ:
注意:CQ 一旦创建就不能修改了,我们必须 DROP 再 CREATE 才行。
DROP CONTINUOUS QUERY "cq_30m" ON "mydb"