InfluxDB インストール - 簡単な使い方


# はじめに
システムのログや検証結果など時間に紐づく情報の入れ場所としてInfluxDBを考えていて、触ってみたのでメモしておく。

# 環境

- OS: CentOS7.1
- InfluxDB: 0.9.2


# InfluxDBとは
https://influxdb.com/
Go製の時系列、メトリックス、分析用のDBでありInfluxDB外部依存はなく単体で動作するtこのこと。

主な特徴は以下とのこと

- 時系列DB
- SQLライクなインターフェースで解析可能
- HTTP(s)のAPIを提供

あとはちょっと触りながら気づいたことをメモしていく。

# インストール
https://influxdb.com/docs/v0.9/introduction/installation.html
にある通りにインストールしてみる。
以下のコマンドでインストール出来る。

```
$ wget http://influxdb.s3.amazonaws.com/influxdb-0.9.2-1.x86_64.rpm
$ sudo yum localinstall influxdb-0.9.2-1.x86_64.rpm
$ 
```

ansibleで書くと以下の感じ。

```
---
- name: be sure yum pkgs are installed    
  yum: name={{item.name}} state=present
  with_items:
    - {name: 'http://influxdb.s3.amazonaws.com/influxdb-0.9.2-1.x86_64.rpm' }

- name: be sure services are 
  service: name={{item.name }} state={{item.state}}
  with_items:
    - {name: 'influxdb', state: 'started'}
```

## 起動
systemctlで起動出来る。

```
$ sudo systemctl start influxdb.service
```

8083ポートにアクセスすると以下の画面が表示される。

## CLIの使い方
https://influxdb.com/docs/v0.9/introduction/getting_started.html
を見るとinfluxというCLIがあるらしい。
以下にある。

```
$ sudo find / -name influx
/opt/influxdb/versions/0.9.2/influx
/opt/influxdb/influx
$
```

pathを通してやる。

```
$ sudo export PATH=/opt/influxdb/:$PATH
```

以下のコマンドでlocal:8086にアクセス。これが管理者用のアクセスポートらしい。

# DB作成
# CLI
まずDBを作成する。
MySQL系のDBと似た感じで操作することが出来そう。


```
$ influx
Connected to http://localhost:8086 version 0.9.2
InfluxDB shell 0.9.2

> SHOW DATABASES
name: databases
---------------
name

> CREATE DATABASE test
> SHOW DATABASES
name: databases
---------------
name
test

> 
```

#### API
以下のHTTPリクエストでも同様のことが出来そう。

```
curl -G http://localhost:8086/query --data-urlencode "q=CREATE DATABASE test2"
{"results":[{}]}$
$ curl -G http://localhost:8086/query --data-urlencode "q=show databases"
{"results":[{"series":[{"name":"databases","columns":["name"],"values":[["test"],["test2"]]}]}]}$
```

作成されている。

# データ作成
## CLI
Getting Startedを見る限りDBを作成すればデータを入れる準備は完了らしい。
以下のコマンドでデータを登録できる。

```
> USE test
Using database test
> INSERT cpu,host=serverA,region=us_west value=0.64
> SELECT * FROM cpu
name: cpu
tags: host=serverA, region=us_west
time				value
----				-----
2015-08-20T16:20:51.85486998Z	0.64

> 

```

SELECT文の結果を見てわかるように、INSERTの最初の項目がテーブル名で、次の空白までがメタデータ、以降が値となるよう。

以下の形式。

```
<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
```

## API
上記で作成したデータは以下のHTTPリクエストで作成可能。

```
$ curl -i -XPOST 'http://localhost:8086/write?db=test2&precision=s' --data-binary 'cpu,host=serverA,region=jp value=0.64 1440319130'
```

> デフォルトではtimestampはnanosecondなので、integerにしたい場合はURLパラメーターにprecision=sを指定する必要がある。
timestampはオプショナルで、指定しない場合はシステム側で指定してくれる。

データを取得してみる。

```
$ curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=test2" --data-urlencode "q=SELECT value FROMcpu WHERE region='jp'"
{
    "results": [
        {
            "series": [
                {
                    "name": "cpu",
                    "columns": [
                        "time",
                        "value"
                    ],
                    "values": [
                        [
                            "2015-08-23T08:38:50Z",
                            0.64
                        ]
                    ]
                }
            ]
        }
    ]
}
$
```

複数のクエリを`;`で繋ぐことで一度のAPIリクエストで複数のクエリを送れるらしい。

```
$ curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=test2" --data-urlencode "q=SELECT value FROM cpu WHERE region='jp';SELECT value FROM cpu WHERE region='jp'"
{
    "results": [
        {
            "series": [
                {
                    "name": "cpu",
                    "columns": [
                        "time",
                        "value"
                    ],
                    "values": [
                        [
                            "2015-08-23T08:38:50Z",
                            0.64
                        ]
                    ]
                }
            ]
        },
        {
            "series": [
                {
                    "name": "cpu",
                    "columns": [
                        "time",
                        "value"
                    ],
                    "values": [
                        [
                            "2015-08-23T08:38:50Z",
                            0.64
                        ]
                    ]
                }
            ]
        }
    ]
}

```

resultsに複数のseriesがArray形式で格納されているよう。

# クエリの書き方
時系列データなので各データは時間に紐付けられていて、時間に関するマクロが充実している。

## 利用データ

```
> SELECT * FROM cpu LIMIT 10;
name: cpu
tags: host=serverA, region=jp_east
time				value
----				-----
2015-08-26T15:27:56.173871955Z	0.68
2015-08-26T15:27:58.335904424Z	0.68
2015-08-26T15:28:00.716265129Z	0.68
2015-08-26T15:28:07.736420541Z	0.68
2015-08-26T15:28:09.956365012Z	0.68
2015-08-26T15:28:14.206256606Z	0.68
2015-08-26T15:28:16.631484237Z	0.68
2015-08-26T15:28:18.473502415Z	0.68
2015-08-26T15:28:19.435090391Z	0.68
2015-08-26T15:30:35.55368872Z	0.68

```

## 集合関数
https://influxdb.com/docs/v0.9/query_language/functions.html
^見ると以下が利用可能。

`GROUP BY time`と一緒に使われることが想定されているとのこと。


- COUNT
- MIN
- MAX
- MEAN
- MEDIAN
- DISTINCT
- PERCENTILE
- DERIVATIVE
- SUM
- STDDEV
- FIRST
- LAST

以下あまり使ったことの無い関数を実行してみた。

### PERCENTILE
第一引数に指定したカラムの中で、第二引数に指定した値の割合に位置するデータを返す。

```
> SELECT PERCENTILE(value,100) FROM cpu WHERE time > now() - 10m GROUP BY time(10s) LIMIT 5;
name: cpu
---------
time			percentile
2015-08-27T02:34:50Z	
2015-08-27T02:35:00Z	0.68
2015-08-27T02:35:10Z	0.68
2015-08-27T02:35:20Z	0.68
2015-08-27T02:35:30Z	0.68

> 
```

### DERIVATIVE
第二引数に指定した時間の直近で、どれぐらい値が変化したかを表す関数かな。

```
> SELECT DERIVATIVE(value,5s) FROM cpu WHERE time > now() - 10m LIMIT 5;
name: cpu
---------
time				value
2015-08-27T02:38:23.875145931Z	0
2015-08-27T02:38:26.035984152Z	0
2015-08-27T02:38:28.195453919Z	0
2015-08-27T02:38:30.35353966Z	0

> 
```

### MEDIAN
中央値。

```
> SELECT MEDIAN(value) FROM cpu WHERE time > now() - 10m GROUP BY time(10s) LIMIT 5;
name: cpu
---------
time			median
2015-08-27T02:28:50Z	
2015-08-27T02:29:00Z	0.68
2015-08-27T02:29:10Z	0.68
2015-08-27T02:29:20Z	0.68
2015-08-27T02:29:30Z	0.68

> 
```

### STDDEV
標準偏差。
全く同じ値のデータを入れているので0となる。

```
> SELECT STDDEV(value) FROM cpu WHERE time > now() - 10m GROUP BY time(10s) LIMIT 5;
name: cpu
---------
time			stddev
2015-08-27T02:29:40Z	0
2015-08-27T02:29:50Z	0
2015-08-27T02:30:00Z	0
2015-08-27T02:30:10Z	0
2015-08-27T02:30:20Z	0

> 
```
## Continuous Queries
https://influxdb.com/docs/v0.9/query_language/continuous_queries.html
を見ると、おそらく集計処理を連続的に実行してその結果を格納するためのクエリ。

以下で登録出来る。

```
> CREATE CONTINUOUS QUERY cpu_max_continuously ON test BEGIN SELECT MAX(value) INTO "cpu_max_continuously" FROM cpu GROUP BY time(10s) END
> SHOW CONTINUOUS QUERIES
name: test
----------
name			query
cpu_max_continuously	CREATE CONTINUOUS QUERY cpu_max_continuously ON test BEGIN SELECT max(value) INTO "test"."default".cpu_max_continuously FROM "test"."default".cpu GROUP BY time(10s) END
>
> SELECT * FROM cpu_max_continuously;
name: cpu_max_continuously
--------------------------
time			max
2015-08-27T02:56:40Z	0.68
2015-08-27T02:56:50Z	0.68
2015-08-27T02:57:00Z	0.68
2015-08-27T02:58:40Z	0.68
2015-08-27T02:58:50Z	0.68

> 
```

データも格納されているよう。
このデータをVisualizationツールで見せれば良さげ。


## 注意点
### GROUP BY time
GROUP BYにtimeを指定するときはWHERE句にtimeが必要。

```
> SELECT mean(value) FROM cpu GROUP BY time(10s);
ERR: error parsing query: aggregate functions with GROUP BY time require a WHERE time clause
>
```

### WHERE句のtimeは左辺に
右辺に指定すると認識されない。

```
> SELECT COUNT(value) FROM cpu WHERE now() > time GROUP BY time(10s);
ERR: error parsing query: aggregate functions with GROUP BY time require a WHERE time clause
> 
```

### WHERE time && GROUP BY time の指定はある程度の個数になるように
あまり調査出来ていないが以下だとGROUP BYしても一つの行しか出力されない。

```
> SELECT COUNT(value) FROM cpu WHERE time < now() GROUP BY time(10s);
name: cpu
---------
time			count
1970-01-01T00:00:00Z	1264

> 
```

直近10分指定の場合は以下のように想定通りに出力される。

> 以下の出力からわかるようにデータがなくても検索結果には出力されるのでこのような作りになっているんだろうなと思う今日この頃。

```
> SELECT COUNT(value) FROM cpu WHERE time > now() - 10m GROUP BY time(10s);
name: cpu
---------
time			count
2015-08-27T01:49:20Z	
2015-08-27T01:49:30Z	4
2015-08-27T01:49:40Z	5
2015-08-27T01:49:50Z	5
2015-08-27T01:50:00Z	4
2015-08-27T01:50:10Z	5
2015-08-27T01:50:20Z	5
2015-08-27T01:50:30Z	4
2015-08-27T01:50:40Z	5
2015-08-27T01:50:50Z	5
2015-08-27T01:51:00Z	4
2015-08-27T01:51:10Z	5
2015-08-27T01:51:20Z	4
2015-08-27T01:51:30Z	5
2015-08-27T01:51:40Z	5
2015-08-27T01:51:50Z	4
2015-08-27T01:52:00Z	5
2015-08-27T01:52:10Z	5
2015-08-27T01:52:20Z	4
2015-08-27T01:52:30Z	5
2015-08-27T01:52:40Z	4
2015-08-27T01:52:50Z	5
2015-08-27T01:53:00Z	5
2015-08-27T01:53:10Z	4
2015-08-27T01:53:20Z	5
2015-08-27T01:53:30Z	5
2015-08-27T01:53:40Z	4
2015-08-27T01:53:50Z	5
2015-08-27T01:54:00Z	5
2015-08-27T01:54:10Z	4
2015-08-27T01:54:20Z	5
2015-08-27T01:54:30Z	4
2015-08-27T01:54:40Z	5
2015-08-27T01:54:50Z	5
2015-08-27T01:55:00Z	4
2015-08-27T01:55:10Z	5
2015-08-27T01:55:20Z	5
2015-08-27T01:55:30Z	4
2015-08-27T01:55:40Z	5
2015-08-27T01:55:50Z	5
2015-08-27T01:56:00Z	4
2015-08-27T01:56:10Z	5
2015-08-27T01:56:20Z	4
2015-08-27T01:56:30Z	5
2015-08-27T01:56:40Z	5
2015-08-27T01:56:50Z	4
2015-08-27T01:57:00Z	5
2015-08-27T01:57:10Z	5
2015-08-27T01:57:20Z	4
2015-08-27T01:57:30Z	5
2015-08-27T01:57:40Z	4
2015-08-27T01:57:50Z	5
2015-08-27T01:58:00Z	5
2015-08-27T01:58:10Z	4
2015-08-27T01:58:20Z	5
2015-08-27T01:58:30Z	5
2015-08-27T01:58:40Z	4
2015-08-27T01:58:50Z	5
2015-08-27T01:59:00Z	5
2015-08-27T01:59:10Z	4
2015-08-27T01:59:20Z	1

>
```

データポイント数が多すぎる場合は以下のようにエラーとなる。

```
> SELECT COUNT(value) FROM cpu WHERE time > now() - 100d GROUP BY time(10s);
ERR: too many points in the group by interval. maybe you forgot to specify a where time clause?
>
```

# おわりに
ちょっと自分が使いそうなところを触って、調べきれていないところがあると思うけどそこらへんはご勘弁をmm

おしまい