一、查询技巧

1. 查询注意事项

  • 由于influxdb的底层设计原因,无法单纯的查询tag,而是需要携带任意的field才可以最终输出数据;
  • 如果需要根据时间进行查询请使用默认的time字段进行时间范围查询;
  • tag存储的数据均为字符串;
  • 查询条件中tag只支持=!=查询,只有field支持其他查询
  • field查询为字符串,对应value需要使用单引号
  • 查询基于当前时间过去的数据使用now()代表当前时间
  • group by只支持tag key和time时间
  • time支持基于时间戳的查询,但是默认是纳秒,如果为秒需要在数字后面增加s
  • 对于查询正则使用=~!~进行匹配与不匹配
  • 类型转换需要在对应字段后面使用::并填入对应类型[float|integer|string|boolean]

2. 数据准备

为了能够保证我们后续的教程可以正常进行读者需要准备相关的数据,这里直接采用
官网提供的数据。具体操作如下:

  1. influx -precision rfc3339
  2. CREATE DATABASE NOAA_water_database
  3. exit

开始下载我们需要的数据文件并导入:

  1. curl https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt -o NOAA_data.txt
  2. influx -import -path=NOAA_data.txt -precision=s -database=NOAA_water_database

如果下载速度较慢,而已考虑使用代理进行加速下载curl -x [http://192.168.28.234:1080](http://192.168.28.234:1080) [https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt](https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt) -o NOAA_data.txt
完成下载后我们可以测试数据是否被正确的导入了:

  1. influx -precision rfc3339 -database NOAA_water_database
  2. SHOW measurements
  3. SELECT COUNT("water_level") FROM h2o_feet
  4. SELECT * FROM h2o_feet LIMIT 5

3. Group By

我们可以按照某个tag key查询特定field的平均值:

  1. SELECT MEAN("water_level") FROM h2o_feet GROUP BY location

当然我们也可以指定多个tab key进行查询:

SELECT MEAN("index") FROM h2o_quality GROUP BY location,randtag

当然我们也可以非常快捷的针对所有tag key进行查询:

SELECT MEAN("index") FROM "h2o_quality" GROUP BY *

更多的场景下我们需要将一个时间范围内的数据按照既定的时间间隔进行查询,所以我们就需要使用GROUP BY time语法
来进行查询,下面我们在限定一个数据范围内按照12分钟间隔进行查询:

SELECT COUNT("water_level") FROM h2o_feet WHERE "location"='coyote_creek' AND time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:30:00Z' GROUP BY time(12m)

当然我们可以继续按照tag key分组:

SELECT COUNT("water_level") FROM h2o_feet WHERE time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:30:00Z' GROUP BY time(12m),location

但如果我们将条件查询的语句时间调整我们会发现输出的数据的时间问题:

SELECT COUNT("water_level") FROM h2o_feet WHERE "location"='coyote_creek' AND time >= '2019-08-18T00:06:00Z' AND time < '2019-08-18T00:18:00Z' GROUP BY time(12m)

我们可以清晰的看到返回的数据时间为2019-08-18T00:00:00Z,按照我们提供的查询范围数据开始时间应该为2019-08-18T00:06:00Z,这是因为GROUP BY的预设时间边界所致,所以我们需要调整
对应的预设时间增加6分钟:

SELECT COUNT("water_level") FROM h2o_feet WHERE "location"='coyote_creek' AND time >= '2019-08-18T00:06:00Z' AND time < '2019-08-18T00:18:00Z' GROUP BY time(12m, 6m)

很多时候我们查询的时间间隔可能存在部分间隔不存在任何数据,就比如下面这样的查询:

SELECT MAX("water_level") FROM "h2o_feet" WHERE "location"='coyote_creek' AND time >= '2019-09-17T16:00:00Z' AND time <= '2019-09-17T16:42:00Z' GROUP BY time(12m)

我们会发现最后一个时间间隔的输出是没有任何值的,这时候我们就需要使用fill了,当然该函数支持如下几种输入以便控制具体的值:

  • 任一数值:用这个数字返回没有数据点的时间间隔
  • linear:返回没有数据的时间间隔的线性插值结果
  • none: 不返回在时间间隔里没有点的数据
  • previous:返回时间隔间的前一个间隔的数据

这里需要注意的是如果查询的范围本身就没有数据即使使用了fill依然也不会有任何数据返回。

SELECT MAX("water_level") FROM "h2o_feet" WHERE "location"='coyote_creek' AND time >= '2019-09-17T16:00:00Z' AND time <= '2019-09-17T16:42:00Z' GROUP BY time(12m) fill(100)

SELECT MAX("water_level") FROM "h2o_feet" WHERE "location"='coyote_creek' AND time >= '2019-09-17T16:00:00Z' AND time <= '2019-09-17T16:42:00Z' GROUP BY time(12m) fill(linear)

SELECT MAX("water_level") FROM "h2o_feet" WHERE "location"='coyote_creek' AND time >= '2019-09-17T16:00:00Z' AND time <= '2019-09-17T16:42:00Z' GROUP BY time(12m) fill(none)

SELECT MAX("water_level") FROM "h2o_feet" WHERE "location"='coyote_creek' AND time >= '2019-09-17T16:00:00Z' AND time <= '2019-09-17T16:42:00Z' GROUP BY time(12m) fill(previous)

4. INTO

考虑到实际使用,这里我们仅介绍在采样过程中的使用案例:

SELECT MEAN("water_level") INTO "all_my_averages" FROM "h2o_feet" WHERE "location" = 'coyote_creek' AND time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:30:00Z' GROUP BY time(12m)

5. ORDER BY

对于基本数据的排序查询我们将使用这种方式查询:

SELECT "water_level" FROM "h2o_feet" WHERE "location" = 'santa_monica' ORDER BY time DESC

如果带有GROUP BY对应的排序需要在这之后:

SELECT MEAN("water_level") FROM "h2o_feet" WHERE time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:42:00Z' GROUP BY time(12m) ORDER BY time DESC

5. LIMIT与SLIMIT

其中LIMIT比较好理解,就是返回当前数据的前几项数据,而对于GROUP BY则是限定每个分组返回的数据数量,比如下面我们查询特定数据并返回我们需要的数量:

SELECT "water_level","location" FROM "h2o_feet" LIMIT 3

以下对应的GROUP BY

SELECT MEAN("water_level") FROM "h2o_feet" WHERE time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:42:00Z' GROUP BY *,time(12m) LIMIT 2

SLIMIT则是限定返回的series的数目,比如上述语句就返回的多个series下的2条数据,而使用的SLIMIT将会限制:

SELECT MEAN("water_level") FROM "h2o_feet" WHERE time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:42:00Z' GROUP BY *,time(12m) LIMIT 2 SLIMIT 1

6. OFFSET与SOFFSET

我们知晓了LIMIT和SLIMIT是用来限定返回的数据多少,如果在分页的情况下我们则需要配合OFFSETSOFFSET来决定跳过对应数量的数据,
比如下面我们将跳过前面3条数据获取后续3条数据:

SELECT "water_level","location" FROM "h2o_feet" LIMIT 3 OFFSET 3

对应的SOFFSET则如下:

SELECT MEAN("water_level") FROM "h2o_feet" WHERE time >= '2019-08-18T00:00:00Z' AND time <= '2019-08-18T00:42:00Z' GROUP BY *,time(12m) ORDER BY time DESC LIMIT 2 OFFSET 2 SLIMIT 1 SOFFSET 1

7. 其他

除了以上对于数值计算的函数以外,还支持其他相关函数进行计算,具体如下所示:

  • MEAN: 计算平均值;
  • MEDIAN: 计算中位数;
  • SPREAD: 计算差值;
  • SUM: 求和;
  • BOTTOM: 返回一个字段中最小的N个值;
  • FIRST: 返回最老的值;
  • LAST: 返回最新的值;
  • MAX: 返回最大;
  • MIN: 返回最小;

二、 元数据查询

  • SHOW DATABASES:查询所有数据库
  • SHOW RETENTION POLICIES:查询指定数据库的保存策略
  • SHOW SERIES:查询指定数据库的series数量
  • SHOW MEASUREMENTS:返回指定数据库的measurements数量
  • SHOW TAG KEYS:返回指定数据库的TAG数量
  • SHOW TAG VALUES:返回指定tag key的tag value数量
  • SHOW FIELD KEYS:返回field key以及数据类型

三、 连续查询

1. 基本使用

由于大多数情况我们采集的数据都是原始数据,数据量非常庞大,并且密度非常细。此时我们就需要对数据进行
加工,从而变成密度相对较粗的数据便于用户查看,当然influxdb天然的提供了连续查询这一功能满足我们的需要。
创建这一语句的基本语法如下:

CREATE CONTINUOUS QUERY <cq_name> ON <database_name>
BEGIN
  <cq_query>
END

其中cq_query就是正常的查询语句,只是该语句必须具备INTOGROUP BY time,结构如下:

SELECT <function[s]> INTO <destination_measurement> FROM <measurement> [WHERE <stuff>] GROUP BY time(<interval>)[,<tag_key[s]>]

下面就是一个简单的将数据保存到其他保存策略的语句:

CREATE CONTINUOUS QUERY "cq_basic_rp" ON "transportation"
BEGIN
  SELECT mean("passengers") INTO "transportation"."three_weeks"."average_passengers" FROM "bus_data" GROUP BY time(1h)
END

由于实际采样中我们可能需要修改数据样本的时间范围以及执行间隔,但是却并不像破坏GROUP BY中设定的值,比如计算1小时数据,但是每个半小时执行,当然
这样会存在覆盖数据,但是也是实际需要。在或者我们需要每半小时计算过去2小时的数据,那么通过高级语法即可实现:

CREATE CONTINUOUS QUERY <cq_name> ON <database_name>
RESAMPLE EVERY <interval> FOR <interval>
BEGIN
  <cq_query>
END

其中EVERY后的interval则为执行间隔时间,而FOR后的interval则为数据范围。

2. 管理查询

此操作仅只能管理员进行。

  • SHOW CONTINUOUS QUERIES:列出当前数据库的持续查询
  • DROP CONTINUOUS QUERY <cq_name> ON <database_name>:删除持续查询