天天看點

時序資料庫InfluxDB使用詳解

1 安裝配置

這裡說一下使用docker容器運作influxdb的步驟,實體機安裝請參照官方文檔。拉取鏡像檔案後運作即可,目前最新版本是1.3.5。啟動容器時設定挂載的資料目錄和開放端口。InfluxDB的操作文法InfluxQL與SQL基本一緻,也提供了一個類似mysql-client的名為influx的CLI。InfluxDB本身是支援分布式部署多副本存儲的,本文介紹都是針對的單節點單副本。

# docker pull influxdb
# docker run -idt --name influxdb -p 8086:8086 -v /Users/ssj/influxdb:/var/lib/influxdb influxdb
f216e9be15bff545befecb30d1d275552026216a939cc20c042b17419e3bde31
[email protected]:/# influx
Connected to http://localhost:8086 version 1.3.5
InfluxDB shell version: 1.3.5
> create database cadvisor  ## 建立資料庫cadvisor
> show databases           
name: databases
name
----
_internal
cadvisor
> CREATE USER testuser WITH PASSWORD 'testpwd' ## 建立使用者和設定密碼
> GRANT ALL PRIVILEGES ON cadvisor TO testuser ## 授權資料庫給指定使用者
> CREATE RETENTION POLICY "cadvisor_retention" ON "cadvisor" DURATION 30d REPLICATION 1 DEFAULT ## 建立預設的資料保留政策,設定儲存時間30天,副本為1
           

2 重要概念

influxdb裡面有一些重要概念:database,timestamp,field key, field value, field set,tag key,tag value,tag set,measurement, retention policy ,series,point。結合下面的例子資料來說明這幾個概念:

name: census
-————————————
time                     butterflies     honeybees     location   scientist
2015-08-18T00:00:00Z      12                23           1         langstroth
2015-08-18T00:00:00Z      1                 30           1         perpetua
2015-08-18T00:06:00Z      11                28           1         langstroth
2015-08-18T00:06:00Z      3                 28           1         perpetua
2015-08-18T05:54:00Z      2                 11           2         langstroth
2015-08-18T06:00:00Z      1                 10           2         langstroth
2015-08-18T06:06:00Z      8                 23           2         perpetua
2015-08-18T06:12:00Z      7                 22           2         perpetua
           

timestamp

既然是時間序列資料庫,influxdb的資料都有一列名為time的列,裡面存儲UTC時間戳。

field key,field value,field set

butterflies和honeybees兩列資料稱為字段(fields),influxdb的字段由field key和field value組成。其中butterflies和honeybees為field key,它們為string類型,用于存儲中繼資料。

而butterflies這一列的資料12-7為butterflies的field value,同理,honeybees這一列的23-22為honeybees的field value。field value可以為string,float,integer或boolean類型。field value通常都是與時間關聯的。

field key和field value對組成的集合稱之為field set。如下:

butterflies = 12 honeybees = 23
butterflies = 1 honeybees = 30
butterflies = 11 honeybees = 28
butterflies = 3 honeybees = 28
butterflies = 2 honeybees = 11
butterflies = 1 honeybees = 10
butterflies = 8 honeybees = 23
butterflies = 7 honeybees = 22
           

在influxdb中,字段必須存在。注意,字段是沒有索引的。如果使用字段作為查詢條件,會掃描符合查詢條件的所有字段值,性能不及tag。類比一下,fields相當于SQL的沒有索引的列。

tag key,tag value,tag set

location和scientist這兩列稱為标簽(tags),标簽由tag key和tag value組成。location這個tag key有兩個tag value:1和2,scientist有兩個tag value:langstroth和perpetua。tag key和tag value對組成了tag set,示例中的tag set如下:

location = 1, scientist = langstroth
location = 2, scientist = langstroth
location = 1, scientist = perpetua
location = 2, scientist = perpetua
           

tags是可選的,但是強烈建議你用上它,因為tag是有索引的,tags相當于SQL中的有索引的列。tag value隻能是string類型 如果你的常用場景是根據butterflies和honeybees來查詢,那麼你可以将這兩個列設定為tag,而其他兩列設定為field,tag和field依據具體查詢需求來定。

measurement

measurement是fields,tags以及time列的容器,measurement的名字用于描述存儲在其中的字段資料,類似mysql的表名。如上面例子中的measurement為census。measurement相當于SQL中的表,本文中我在部分地方會用表來指代measurement。

retention policy

retention policy指資料保留政策,示例資料中的retention policy為預設的autogen。它表示資料一直保留永不過期,副本數量為1。你也可以指定資料的保留時間,如30天。

series

series是共享同一個retention policy,measurement以及tag set的資料集合。示例中資料有4個series,如下:

Arbitrary series number Retention policy Measurement Tag set
series 1 autogen census location = 1,scientist = langstroth
series 2 autogen census location = 2,scientist = langstroth
series 3 autogen census location = 1,scientist = perpetua
series 4 autogen census location = 2,scientist = perpetua

point

point則是同一個series中具有相同時間的field set,points相當于SQL中的資料行。如下面就是一個point:

name: census
-----------------
time                  butterflies    honeybees   location    scientist
2015-08-18T00:00:00Z       1            30           1        perpetua
           

database

上面提到的結構都存儲在資料庫中,示例的資料庫為my_database。一個資料庫可以有多個measurement,retention policy, continuous queries以及user。influxdb是一個無模式的資料庫,可以很容易的添加新的measurement,tags,fields等。而它的操作卻和傳統的資料庫一樣,可以使用類SQL語言查詢和修改資料。

influxdb不是一個完整的CRUD資料庫,它更像是一個CR-ud資料庫。它優先考慮的是增加和讀取資料而不是更新和删除資料的性能,而且它阻止了某些更新和删除行為使得建立和讀取資料更加高效。

3 特色函數

influxdb函數分為聚合函數,選擇函數,轉換函數,預測函數等。除了與普通資料庫一樣提供了基本操作函數外,還提供了一些特色函數以友善資料統計計算,下面會一一介紹其中一些常用的特色函數。

  • 聚合函數:

    FILL()

    ,

    INTEGRAL()

    SPREAD()

    STDDEV()

    MEAN()

    ,

    MEDIAN()

    等。
  • 選擇函數:

    SAMPLE()

    ,

    PERCENTILE()

    ,

    FIRST()

    ,

    LAST()

    ,

    TOP()

    ,

    BOTTOM()

    等。
  • 轉換函數:

    DERIVATIVE()

    ,

    DIFFERENCE()

    等。
  • 預測函數:

    HOLT_WINTERS()

先從官網導入測試資料(注:這裡測試用的版本是1.3.1,最新版本是1.3.5):

$ curl https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt -o NOAA_data.txt
$ influx -import -path=NOAA_data.txt -precision=s -database=NOAA_water_database
$ influx -precision rfc3339 -database NOAA_water_database
Connected to http://localhost:8086 version 1.3.1
InfluxDB shell 1.3.1
> show measurements
name: measurements
name
----
average_temperature
distincts
h2o_feet
h2o_pH
h2o_quality
h2o_temperature

> show series from h2o_feet;
key
---
h2o_feet,location=coyote_creek
h2o_feet,location=santa_monica
           

下面的例子都以官方示例資料庫來測試,這裡隻用部分資料以友善觀察。measurement為

h2o_feet

,tag key為

location

,field key有

level description

water_level

兩個。

> SELECT * FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z'
name: h2o_feet
time                 level description    location     water_level
----                 -----------------    --------     -----------
2015-08-18T00:00:00Z between 6 and 9 feet coyote_creek 8.12
2015-08-18T00:00:00Z below 3 feet         santa_monica 2.064
2015-08-18T00:06:00Z between 6 and 9 feet coyote_creek 8.005
2015-08-18T00:06:00Z below 3 feet         santa_monica 2.116
2015-08-18T00:12:00Z between 6 and 9 feet coyote_creek 7.887
2015-08-18T00:12:00Z below 3 feet         santa_monica 2.028
2015-08-18T00:18:00Z between 6 and 9 feet coyote_creek 7.762
2015-08-18T00:18:00Z below 3 feet         santa_monica 2.126
2015-08-18T00:24:00Z between 6 and 9 feet coyote_creek 7.635
2015-08-18T00:24:00Z below 3 feet         santa_monica 2.041
2015-08-18T00:30:00Z between 6 and 9 feet coyote_creek 7.5
2015-08-18T00:30:00Z below 3 feet         santa_monica 2.051
           

GROUP BY,FILL()

如下語句中

GROUP BY time(12m),*

表示以每12分鐘和tag(location)分組(如果是

GROUP BY time(12m)

則表示僅每12分鐘分組,GROUP BY 參數隻能是time和tag)。然後fill(200)表示如果這個時間段沒有資料,以200填充,mean(field_key)求該範圍内資料的平均值(注意:這是依據series來計算。其他還有SUM求和,MEDIAN求中位數)。LIMIT 7表示限制傳回的point(記錄數)最多為7條,而SLIMIT 1則是限制傳回的series為1個。

注意這裡的時間區間,起始時間為整點前包含這個區間第一個12m的時間,比如這裡為

2015-08-17T:23:48:00Z

,第一條為

2015-08-17T23:48:00Z <= t < 2015-08-18T00:00:00Z

這個區間的

location=coyote_creek

water_level

的平均值,這裡沒有資料,于是填充的200。第二條為

2015-08-18T00:00:00Z <= t < 2015-08-18T00:12:00Z

區間的

location=coyote_creek

water_level

平均值,這裡為

(8.12+8.005)/ 2 = 8.0625

,其他以此類推。

GROUP BY time(10m)

則表示以10分鐘分組,起始時間為包含這個區間的第一個10m的時間,即

2015-08-17T23:40:00Z

。預設傳回的是第一個series,如果要計算另外那個series,可以在SQL語句後面加上

SOFFSET 1

那如果時間小于資料本身采集的時間間隔呢,比如

GROUP BY time(10s)

呢?這樣的話,就會按10s取一個點,沒有數值的為空或者FILL填充,對應時間點有資料則保持不變。

## GROUP BY time(12m)
> SELECT mean("water_level") FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(12m),* fill(200) LIMIT 7 SLIMIT 1
name: h2o_feet
tags: location=coyote_creek
time                 mean
----                 ----
2015-08-17T23:48:00Z 200
2015-08-18T00:00:00Z 8.0625
2015-08-18T00:12:00Z 7.8245
2015-08-18T00:24:00Z 7.5675

## GROUP BY time(10m),SOFFSET設定為1
> SELECT mean("water_level") FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(10m),* fill(200) LIMIT 7 SLIMIT 1 SOFFSET 1
name: h2o_feet
tags: location=santa_monica
time                 mean
----                 ----
2015-08-17T23:40:00Z 200
2015-08-17T23:50:00Z 200
2015-08-18T00:00:00Z 2.09
2015-08-18T00:10:00Z 2.077
2015-08-18T00:20:00Z 2.041
2015-08-18T00:30:00Z 2.051
           

INTEGRAL(field_key, unit)

計算數值字段值覆寫的曲面的面積值并得到面積之和。測試資料如下:

> SELECT "water_level" FROM "h2o_feet" WHERE "location" = 'santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z'

name: h2o_feet
time                   water_level
----                   -----------
2015-08-18T00:00:00Z   2.064
2015-08-18T00:06:00Z   2.116
2015-08-18T00:12:00Z   2.028
2015-08-18T00:18:00Z   2.126
2015-08-18T00:24:00Z   2.041
2015-08-18T00:30:00Z   2.051
           

使用INTERGRAL計算面積。注意,這個面積就是這些點連接配接起來後與時間圍成的不規則圖形的面積,注意unit預設是以1秒計算,是以下面語句計算結果為

3732.66=2.028*1800+分割出來的梯形和三角形面積

。如果unit改為1分,則結果為

3732.66/60 = 62.211

。unit為2分,則結果為

3732.66/120 = 31.1055

。以此類推。

# unit為預設的1秒
> SELECT INTEGRAL("water_level") FROM "h2o_feet" WHERE "location" = 'santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z'
name: h2o_feet
time                 integral
----                 --------
1970-01-01T00:00:00Z 3732.66

# unit為1分
> SELECT INTEGRAL("water_level", 1m) FROM "h2o_feet" WHERE "location" = 'santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z'
name: h2o_feet
time                 integral
----                 --------
1970-01-01T00:00:00Z 62.211
           

SPREAD(field_key)

計算數值字段的最大值和最小值的內插補點。

> SELECT SPREAD("water_level") FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(12m),* fill(18) LIMIT 3 SLIMIT 1 SOFFSET 1
name: h2o_feet
tags: location=santa_monica
time                 spread
----                 ------
2015-08-17T23:48:00Z 18
2015-08-18T00:00:00Z 0.052000000000000046
2015-08-18T00:12:00Z 0.09799999999999986
           

STDDEV(field_key)

計算字段的标準差。influxdb用的是貝塞爾修正的标準差計算公式 ,如下:

  • mean=(v1+v2+...+vn)/n;
  • stddev = math.sqrt(

    ((v1-mean)2 + (v2-mean)2 + ...+(vn-mean)2)/(n-1)

    )

> SELECT STDDEV("water_level") FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(12m),* fill(18) SLIMIT 1;
name: h2o_feet
tags: location=coyote_creek
time                 stddev
----                 ------
2015-08-17T23:48:00Z 18
2015-08-18T00:00:00Z 0.08131727983645186
2015-08-18T00:12:00Z 0.08838834764831845
2015-08-18T00:24:00Z 0.09545941546018377
           

PERCENTILE(field_key, N)

選取某個字段中大于N%的這個字段值。

如果一共有4條記錄,N為10,則10%*4=0.4,四舍五入為0,則查詢結果為空。N為20,則 20% * 4 = 0.8,四舍五入為1,選取的是4個數中最小的數。如果N為40,40% * 4 = 1.6,四舍五入為2,則選取的是4個數中第二小的數。由此可以看出N=100時,就跟

MAX(field_key)

是一樣的,而當N=50時,與

MEDIAN(field_key)

在字段值為奇數個時是一樣的。

> SELECT PERCENTILE("water_level",20) FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(12m)
name: h2o_feet
time                 percentile
----                 ----------
2015-08-17T23:48:00Z 
2015-08-18T00:00:00Z 2.064
2015-08-18T00:12:00Z 2.028
2015-08-18T00:24:00Z 2.041

> SELECT PERCENTILE("water_level",40) FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(12m)
name: h2o_feet
time                 percentile
----                 ----------
2015-08-17T23:48:00Z 
2015-08-18T00:00:00Z 2.116
2015-08-18T00:12:00Z 2.126
2015-08-18T00:24:00Z 2.051
           

SAMPLE(field_key, N)

随機傳回field key的N個值。如果語句中有

GROUP BY time()

,則每組資料随機傳回N個值。

> SELECT SAMPLE("water_level",2) FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z';
name: h2o_feet
time                 sample
----                 ------
2015-08-18T00:00:00Z 2.064
2015-08-18T00:12:00Z 2.028

> SELECT SAMPLE("water_level",2) FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z' GROUP BY time(12m);
name: h2o_feet
time                 sample
----                 ------
2015-08-18T00:06:00Z 2.116
2015-08-18T00:06:00Z 8.005
2015-08-18T00:12:00Z 7.887
2015-08-18T00:18:00Z 7.762
2015-08-18T00:24:00Z 7.635
2015-08-18T00:30:00Z 2.051
           

CUMULATIVE_SUM(field_key)

計算字段值的遞增和。

> SELECT CUMULATIVE_SUM("water_level") FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:30:00Z';
name: h2o_feet
time                 cumulative_sum
----                 --------------
2015-08-18T00:00:00Z 8.12
2015-08-18T00:00:00Z 10.184
2015-08-18T00:06:00Z 18.189
2015-08-18T00:06:00Z 20.305
2015-08-18T00:12:00Z 28.192
2015-08-18T00:12:00Z 30.22
2015-08-18T00:18:00Z 37.982
2015-08-18T00:18:00Z 40.108
2015-08-18T00:24:00Z 47.742999999999995
2015-08-18T00:24:00Z 49.78399999999999
2015-08-18T00:30:00Z 57.28399999999999
2015-08-18T00:30:00Z 59.334999999999994
           

DERIVATIVE(field_key, unit) 和 NON_NEGATIVE_DERIVATIVE(field_key, unit)

計算字段值的變化比。unit預設為1s,即計算的是1秒内的變化比。

如下面的第一個資料計算方法是

(2.116-2.064)/(6*60) = 0.00014..

,其他計算方式同理。雖然原始資料是6m收集一次,但是這裡的變化比預設是按秒來計算的。如果要按6m計算,則設定unit為6m即可。

> SELECT DERIVATIVE("water_level") FROM "h2o_feet" WHERE "location" = 'santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z'
name: h2o_feet
time                 derivative
----                 ----------
2015-08-18T00:06:00Z 0.00014444444444444457
2015-08-18T00:12:00Z -0.00024444444444444465
2015-08-18T00:18:00Z 0.0002722222222222218
2015-08-18T00:24:00Z -0.000236111111111111
2015-08-18T00:30:00Z 0.00002777777777777842

> SELECT DERIVATIVE("water_level", 6m) FROM "h2o_feet" WHERE "location" = 'santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z'
name: h2o_feet
time                 derivative
----                 ----------
2015-08-18T00:06:00Z 0.052000000000000046
2015-08-18T00:12:00Z -0.08800000000000008
2015-08-18T00:18:00Z 0.09799999999999986
2015-08-18T00:24:00Z -0.08499999999999996
2015-08-18T00:30:00Z 0.010000000000000231
           

而DERIVATIVE結合GROUP BY time,以及mean可以構造更加複雜的查詢,如下所示:

> SELECT DERIVATIVE(mean("water_level"), 6m) FROM "h2o_feet" WHERE time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z' group by time(12m), *
name: h2o_feet
tags: location=coyote_creek
time                 derivative
----                 ----------
2015-08-18T00:12:00Z -0.11900000000000022
2015-08-18T00:24:00Z -0.12849999999999984

name: h2o_feet
tags: location=santa_monica
time                 derivative
----                 ----------
2015-08-18T00:12:00Z -0.00649999999999995
2015-08-18T00:24:00Z -0.015499999999999847
           

這個計算其實是先根據GROUP BY time求平均值,然後對這個平均值再做變化比的計算。因為資料是按12分鐘分組的,而變化比的unit是6分鐘,是以內插補點除以2(12/6)才得到變化比。如第一個值是

(7.8245-8.0625)/2 = -0.1190

> SELECT mean("water_level") FROM "h2o_feet" WHERE time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z' group by time(12m), *
name: h2o_feet
tags: location=coyote_creek
time                 mean
----                 ----
2015-08-18T00:00:00Z 8.0625
2015-08-18T00:12:00Z 7.8245
2015-08-18T00:24:00Z 7.5675

name: h2o_feet
tags: location=santa_monica
time                 mean
----                 ----
2015-08-18T00:00:00Z 2.09
2015-08-18T00:12:00Z 2.077
2015-08-18T00:24:00Z 2.0460000000000003
           

NON_NEGATIVE_DERIVATIVE

DERIVATIVE

不同的是它隻傳回的是非負的變化比:

> SELECT DERIVATIVE(mean("water_level"), 6m) FROM "h2o_feet" WHERE location='santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z' group by time(6m), *
name: h2o_feet
tags: location=santa_monica
time                 derivative
----                 ----------
2015-08-18T00:06:00Z 0.052000000000000046
2015-08-18T00:12:00Z -0.08800000000000008
2015-08-18T00:18:00Z 0.09799999999999986
2015-08-18T00:24:00Z -0.08499999999999996
2015-08-18T00:30:00Z 0.010000000000000231

> SELECT NON_NEGATIVE_DERIVATIVE(mean("water_level"), 6m) FROM "h2o_feet" WHERE location='santa_monica' AND time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:30:00Z' group by time(6m), *
name: h2o_feet
tags: location=santa_monica
time                 non_negative_derivative
----                 -----------------------
2015-08-18T00:06:00Z 0.052000000000000046
2015-08-18T00:18:00Z 0.09799999999999986
2015-08-18T00:30:00Z 0.010000000000000231
           

4 連續查詢

4.1 基本文法

連續查詢(CONTINUOUS QUERY,簡寫為CQ)是指定時自動在實時資料上進行的InfluxQL查詢,查詢結果可以存儲到指定的measurement中。基本文法格式如下:

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

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

           

CQ操作的是實時資料,它使用本地伺服器的時間戳、GROUP BY time()時間間隔以及InfluxDB預先設定好的時間範圍來确定什麼時候開始查詢以及查詢覆寫的時間範圍。注意CQ語句裡面的WHERE條件是沒有時間範圍的,因為CQ會根據

GROUP BY time()

自動确定時間範圍。

CQ執行的時間間隔和

GROUP BY time()

的時間間隔一樣,它在InfluxDB預先設定的時間範圍的起始時刻執行。如果

GROUP BY time(1h)

,則單次查詢的時間範圍為

now()-GROUP BY time(1h)

now()

,也就是說,如果目前時間為17點,這次查詢的時間範圍為 16:00到16:59.99999。

下面看幾個示例,示例資料如下,這是資料庫

transportation

中名為

bus_data

的measurement,每15分鐘統計一次乘客數和投訴數。資料檔案

bus_data.txt

如下:

# DDL
CREATE DATABASE transportation

# DML
# CONTEXT-DATABASE: transportation 

bus_data,complaints=9 passengers=5 1472367600
bus_data,complaints=9 passengers=8 1472368500
bus_data,complaints=9 passengers=8 1472369400
bus_data,complaints=9 passengers=7 1472370300
bus_data,complaints=9 passengers=8 1472371200
bus_data,complaints=7 passengers=15 1472372100
bus_data,complaints=7 passengers=15 1472373000
bus_data,complaints=7 passengers=17 1472373900
bus_data,complaints=7 passengers=20 1472374800
           

導入資料,指令如下:

[email protected]:/# influx -import -path=bus_data.txt -precision=s
[email protected]:/# influx -precision=rfc3339 -database=transportation
Connected to http://localhost:8086 version 1.3.5
InfluxDB shell version: 1.3.5
> select * from bus_data
name: bus_data
time                 complaints passengers
----                 ---------- ----------
2016-08-28T07:00:00Z 9          5
2016-08-28T07:15:00Z 9          8
2016-08-28T07:30:00Z 9          8
2016-08-28T07:45:00Z 9          7
2016-08-28T08:00:00Z 9          8
2016-08-28T08:15:00Z 7          15
2016-08-28T08:30:00Z 7          15
2016-08-28T08:45:00Z 7          17
2016-08-28T09:00:00Z 7          20
           

示例1 自動縮小取樣存儲到新的measurement中

對單個字段自動縮小取樣并存儲到新的measurement中。

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

這個CQ的意思就是對

bus_data

每小時自動計算取樣資料的平均乘客數并存儲到

average_passengers

中。那麼在2016-08-28這天早上會執行如下流程:

At 8:00 cq_basic 執行查詢,查詢時間範圍 time >= '7:00' AND time < '08:00'.
cq_basic寫入一條記錄到 average_passengers:
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   7
At 9:00 cq_basic 執行查詢,查詢時間範圍 time >= '8:00' AND time < '9:00'.
cq_basic寫入一條記錄到 average_passengers:
name: average_passengers
------------------------
time                   mean
2016-08-28T08:00:00Z   13.75

# Results
> SELECT * FROM "average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   7
2016-08-28T08:00:00Z   13.75
           

示例2 自動縮小取樣并存儲到新的保留政策(Retention Policy)中

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
           

與示例1類似,不同的是保留的政策不是

autogen

,而是改成了

three_weeks

(建立保留政策文法

CREATE RETENTION POLICY "three_weeks" ON "transportation" DURATION 3w REPLICATION 1

)。

> SELECT * FROM "transportation"."three_weeks"."average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   7
2016-08-28T08:00:00Z   13.75
           

示例3 使用後向引用(backreferencing)自動縮小取樣并存儲到新的資料庫中

CREATE CONTINUOUS QUERY "cq_basic_br" ON "transportation"
BEGIN
  SELECT mean(*) INTO "downsampled_transportation"."autogen".:MEASUREMENT FROM /.*/ GROUP BY time(30m),*
END
           

使用後向引用文法自動縮小取樣并存儲到新的資料庫中。文法

:MEASUREMENT

用來指代後面的表,而

/.*/

則是分别查詢所有的表。這句CQ的含義就是每30分鐘自動查詢

transportation

的所有表(這裡隻有bus_data一個表),并将30分鐘内數字字段(passengers和complaints)求平均值存儲到新的資料庫

downsampled_transportation

中。

最終結果如下:

> SELECT * FROM "downsampled_transportation."autogen"."bus_data"
name: bus_data
--------------
time                   mean_complaints   mean_passengers
2016-08-28T07:00:00Z   9                 6.5
2016-08-28T07:30:00Z   9                 7.5
2016-08-28T08:00:00Z   8                 11.5
2016-08-28T08:30:00Z   7                 16
           

示例4 自動縮小取樣以及配置CQ的時間範圍

CREATE CONTINUOUS QUERY "cq_basic_offset" ON "transportation"
BEGIN
  SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(1h,15m)
END
           

與前面幾個示例不同的是,這裡的

GROUP BY time(1h, 15m)

指定了一個時間偏移,也就是說

cq_basic_offset

執行的時間不再是整點,而是往後偏移15分鐘。執行流程如下:

At 8:15 cq_basic_offset 執行查詢的時間範圍 time >= '7:15' AND time < '8:15'.
name: average_passengers
------------------------
time                   mean
2016-08-28T07:15:00Z   7.75
At 9:15 cq_basic_offset 執行查詢的時間範圍 time >= '8:15' AND time < '9:15'.
name: average_passengers
------------------------
time                   mean
2016-08-28T08:15:00Z   16.75
           

最終結果:

> SELECT * FROM "average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T07:15:00Z   7.75
2016-08-28T08:15:00Z   16.75
           

4.2 進階文法

InfluxDB連續查詢的進階文法如下:

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

與基本文法不同的是,多了

RESAMPLE

關鍵字。進階文法裡CQ的執行時間和查詢時間範圍則與RESAMPLE裡面的兩個interval有關系。

進階文法中CQ以EVERY interval的時間間隔執行,執行時查詢的時間範圍則是FOR interval來确定。如果FOR interval為2h,目前時間為17:00,則查詢的時間範圍為

15:00-16:59.999999

。RESAMPLE的EVERY和FOR兩個關鍵字可以隻有一個。

示例的資料表如下,比之前的多了幾條記錄為了示例3和示例4的測試:

name: bus_data
--------------
time                   passengers
2016-08-28T06:30:00Z   2
2016-08-28T06:45:00Z   4
2016-08-28T07:00:00Z   5
2016-08-28T07:15:00Z   8
2016-08-28T07:30:00Z   8
2016-08-28T07:45:00Z   7
2016-08-28T08:00:00Z   8
2016-08-28T08:15:00Z   15
2016-08-28T08:30:00Z   15
2016-08-28T08:45:00Z   17
2016-08-28T09:00:00Z   20
           

示例1 隻配置執行時間間隔

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
           

這裡配置了30分鐘執行一次CQ,沒有指定FOR interval,于是查詢的時間範圍還是

GROUP BY time(1h)

指定的一個小時,執行流程如下:

At 8:00, cq_advanced_every 執行時間範圍 time >= '7:00' AND time < '8:00'.
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   7
At 8:30, cq_advanced_every 執行時間範圍 time >= '8:00' AND time < '9:00'.
name: average_passengers
------------------------
time                   mean
2016-08-28T08:00:00Z   12.6667
At 9:00, cq_advanced_every 執行時間範圍 time >= '8:00' AND time < '9:00'.
name: average_passengers
------------------------
time                   mean
2016-08-28T08:00:00Z   13.75
           

需要注意的是,這裡的 8點到9點這個區間執行了兩次,第一次執行時時8:30,平均值是

(8+15+15)/ 3 = 12.6667

,而第二次執行時間是9:00,平均值是

(8+15+15+17) / 4=13.75

,而且最後第二個結果覆寫了第一個結果。InfluxDB如何處理重複的記錄可以參見這個文檔。

最終結果:

> SELECT * FROM "average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   7
2016-08-28T08:00:00Z   13.75
           

示例2 隻配置查詢時間範圍

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分鐘分組,是以每次會寫入兩條記錄。執行流程如下:

At 8:00 cq_advanced_for 查詢時間範圍:time >= '7:00' AND time < '8:00'.
寫入兩條記錄。
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   6.5
2016-08-28T07:30:00Z   7.5
At 8:30 cq_advanced_for 查詢時間範圍:time >= '7:30' AND time < '8:30'.
寫入兩條記錄。
name: average_passengers
------------------------
time                   mean
2016-08-28T07:30:00Z   7.5
2016-08-28T08:00:00Z   11.5
At 9:00 cq_advanced_for 查詢時間範圍:time >= '8:00' AND time < '9:00'.
寫入兩條記錄。
name: average_passengers
------------------------
time                   mean
2016-08-28T08:00:00Z   11.5
2016-08-28T08:30:00Z   16
           

需要注意的是,

cq_advanced_for

每次寫入了兩條記錄,重複的記錄會被覆寫。

最終結果:

> SELECT * FROM "average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T07:00:00Z   6.5
2016-08-28T07:30:00Z   7.5
2016-08-28T08:00:00Z   11.5
2016-08-28T08:30:00Z   16
           

示例3 同時配置執行時間間隔和查詢時間範圍

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分鐘,每次插入了三條記錄。執行流程如下:

At 8:00 cq_advanced_every_for 查詢時間範圍 time >= '6:30' AND time < '8:00'.
插入三條記錄
name: average_passengers
------------------------
time                   mean
2016-08-28T06:30:00Z   3
2016-08-28T07:00:00Z   6.5
2016-08-28T07:30:00Z   7.5
At 9:00 cq_advanced_every_for 查詢時間範圍 time >= '7:30' AND time < '9:00'.
插入三條記錄
name: average_passengers
------------------------
time                   mean
2016-08-28T07:30:00Z   7.5
2016-08-28T08:00:00Z   11.5
2016-08-28T08:30:00Z   16
           

最終結果:

> SELECT * FROM "average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T06:30:00Z   3
2016-08-28T07:00:00Z   6.5
2016-08-28T07:30:00Z   7.5
2016-08-28T08:00:00Z   11.5
2016-08-28T08:30:00Z   16
           

示例4 配置查詢時間範圍和FILL填充

CREATE CONTINUOUS QUERY "cq_advanced_for_fill" ON "transportation"
RESAMPLE FOR 2h
BEGIN
  SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(1h) fill(1000)
END
           

在前面值配置查詢時間範圍的基礎上,加上FILL填充空的記錄。執行流程如下:

At 6:00, cq_advanced_for_fill 查詢時間範圍:time >= '4:00' AND time < '6:00',沒有資料,不填充。

At 7:00, cq_advanced_for_fill 查詢時間範圍:time >= '5:00' AND time < '7:00'. 寫入兩條記錄,沒有資料的時間點填充1000。
------------------------
time                   mean
2016-08-28T05:00:00Z   1000          <------ fill(1000)
2016-08-28T06:00:00Z   3             <------ average of 2 and 4

[…] At 11:00, cq_advanced_for_fill 查詢時間範圍:time >= '9:00' AND time < '11:00'.寫入兩條記錄,沒有資料的點填充1000。
name: average_passengers
------------------------
2016-08-28T09:00:00Z   20            <------ average of 20
2016-08-28T10:00:00Z   1000          <------ fill(1000)     

At 12:00, cq_advanced_for_fill 查詢時間範圍:time >= '10:00' AND time < '12:00'。沒有資料,不填充。
           

最終結果:

> SELECT * FROM "average_passengers"
name: average_passengers
------------------------
time                   mean
2016-08-28T05:00:00Z   1000
2016-08-28T06:00:00Z   3
2016-08-28T07:00:00Z   7
2016-08-28T08:00:00Z   13.75
2016-08-28T09:00:00Z   20
2016-08-28T10:00:00Z   1000
           

轉載于:https://www.cnblogs.com/zhangboyu/p/7503543.html