みかんのゆるふわ技術ブログ

Raspberry PiやIoT関係のことを書き残していきます

時系列データベース InfluxDBとは?

InfluxDBはInfluxDataというアメリカの会社が開発しているオープンソースの時系列データベースです。

時系列データベースというのは、サーバーのログや、センサーのデータなど、タイムスタンプに紐づいたデータを扱うのに便利なデータベースです。 時系列データベースと呼ばれるものは、他にもOpenTSDB、Graphite、Prometheusなどがあります。

中でもInfluxDBはオープンソース版が無料で使えることや、ドキュメントがしっかりしていること、Grafanaというデータ可視化ソフトウェアと連携してセンサー可視化が簡単にできることなどから、趣味の用途でも良く使われていると思います。

ここでは、そんなInfluxDBを趣味用途で使うレベルで、簡単に紹介してみたいと思います。

InfluxDBとは

特徴

docs.influxdata.com

こちらのページにInfluxDBの特徴が挙げられていますが、特にこういう特徴があります。

  • 時系列データに特化した高性能データストア
  • ソースコードはGoで書かれ、外部依存のない単一のバイナリになる
  • シンプルで高性能な読み書きHTTP APIが付属
  • SQLっぽいクエリ言語が使え、簡単にデータにクエリや集計ができる

特に、HTTPで簡単にデータ投入やクエリができるのが、趣味でちょっと使うのに便利です。

もちろん、商用の大規模システムにも十分適用できる性能と機能を持っているので、そういうシステムの開発者にはもっとピッタリかもしれません。 詳しくは、InfluxDBの公式ドキュメントを参照してください。

データ形式

InfluxDBのデータベースには、MeasurementPointFieldTagsなどの概念があります。

f:id:kimura_khs:20200819183059p:plain

Measurementは、リレーショナルデーターベースでいうテーブルのようなものです。

Pointというのはレコードのようなもので、タイムスタンプとFieldから構成されます。 Fieldは例えば、temperature=23.4といったKey-Value形式となります。

また、PointにはTagを付けることもできます。例えば、location=bedroomなどとKey-Value形式のタグを付与できます。 Tagsはインデックス化されるので、クエリの際に効率的に抽出できます。

インストール

Ubuntu 18.04 LTSにインストールするには、次のようにします。

まずは、InfluxDBのパッケージリポジトリを追加します。

$ wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -
$ source /etc/lsb-release
$ echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
$ sudo apt-get update

これで、APTでInfluxDBをインストールできる準備が整いました。あとは、次のコマンドでインストールできます。

$ sudo apt-get install influxdb

起動時に自動的にInfluxDBも起動するようにしておきましょう。

$ sudo systemctl unmask influxdb.service
$ sudo systemctl start influxdb

デフォルトでは、TCP 8086番ポートでHTTP APIによるクエリやデータ投入を受け付けます。 設定ファイルが/etc/influxdb/influxdb.confにあり、ポート番号の変更や、HTTP APIに認証を付けるなど、様々な設定ができます。

スポンサーリンク

使ってみよう

データベース作成

InfluxDBをインストールすると、influxというコマンドが使えるようになります。 このコマンドでInfluxDBを操作できる専用のシェルが起動します。ちなみに、exitコマンドで終了できます。

$ influx
Connected to http://localhost:8086 version 1.8.1
InfluxDB shell version: 1.8.1
>

まずは、SHOW DATABASESコマンドで、今あるデータベースを見てみましょう。InfluxDBは複数のデータベースを持つことができます。

> SHOW DATABASEAS
name: databases
name
----
_internal

初期状態では、InfluxDBが内部で使う_internalというデータベースだけが存在します。

CREATE DATABASEコマンドで、データベースを作成できます。引数に、データベース名を取ります。mydbという名前のデータベースを作成してみましょう。

> CREATE DATABASE mydb
> SHOW DATABASEAS
name: databases
name
----
_internal
mydb

mydbというデータベースができましたね。ついでに、DROP DATABASEコマンドでデータベースを削除できます。 データベース内のあらゆるデータが消えますので、削除の際は十分に注意してください。先ほど作成したmydbを削除してみましょう。

> DROP DATABASE mydb
> SHOW DATABASES
name: databases
name
----
_internal

消えましたね。後で使うので、再度作っておきましょう。

> CREATE DATABASE mydb

今後このシェルでmydbを操作するために、USEコマンドでデータベースを選択します。

> USE mydb
Using database mydb

データの書き込み

Pointの書き込みは、InfluxDB Line Protocolと呼ばれる、以下の1行形式で行います。1行が1つのPointとなります。

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

例えば、次のようになります。

sensor,room=bedroom temperature=23.4,humidity=67.8,barometer=1023.4 1597746439000000000

これは、measurementがsensorで、タグとしてroom=bedroomを持ちます。また、測定値として温度、湿度、気圧をそれぞれ持っています。最後はタイムスタンプはナノ秒単位でUNIXタイムスタンプを持っています。

INSERTコマンドで書き込みができます。

> INSERT sensor,room=bedroom temperature=23.4,humidity=67.8,barometer=1023.4 1597746439000000000

measurementが存在しない場合は自動的に作られるようです。なお、show measurementsでmeasurementの一覧が見られます。

データのクエリ

SELECTコマンドでデータのクエリができます。

> SELECT * FROM sensor
name: sensor
time                barometer humidity room    temperature
----                --------- -------- ----    -----------
1597746439000000000 1023.4    67.8     bedroom 23.4

SQLみたいに、WHERE節で条件を指定したり、様々なクエリを発行できます。 詳しくは、ドキュメントを参照してください。

スポンサーリンク

HTTP APIを使ってみよう

InfluxDBの特徴の1つが、HTTP APIを持っていることです。 これにより、様々なプログラミング言語やシェルスクリプトでもInfluxDBを簡単に扱えます。

ここでは、curlコマンドでの操作例を示します。

データーベース作成

データベース作成は、/queryq=CREATE DATABASE <new_database_name>をPOSTします。

$ curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"

データの書き込み

データの書き込みURIは、/write?db=mydbのようにクエリパラメータでデータベース名を指定してPOSTします。 データは上記influxdbコマンドでの書き込み形式と全く同じです。

$ curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary \
'sensor,room=bedroom temperature=23.4,humidity=67.8,barometer=1023.4 1597746439000000000'

成功すると、204が返るようです。次のような応答が帰りました。

HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: 00daf013-e1f7-11ea-800c-b827eb8327ef
X-Influxdb-Build: OSS
X-Influxdb-Version: 1.8.1
X-Request-Id: 00daf013-e1f7-11ea-800c-b827eb8327ef
Date: Wed, 19 Aug 2020 08:35:57 GMT

なお、改行コードを入れてデータを複数行にすることで、複数のデータを1回のHTTPリクエストで書き込むこともできます。

$ curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary \
'sensor,room=bedroom temperature=23.4,humidity=67.8,barometer=1023.4 1597746439000000000
sensor,room=bedroom temperature=23.5,humidity=67.9,barometer=1023.3 1597746499000000000'

これも同じく204が返りました。

HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: 5993109b-e1f7-11ea-8010-b827eb8327ef
X-Influxdb-Build: OSS
X-Influxdb-Version: 1.8.1
X-Request-Id: 5993109b-e1f7-11ea-8010-b827eb8327ef
Date: Wed, 19 Aug 2020 08:38:26 GMT

データのクエリ

/queryにGETリクエストを送ります。その際、クエリパラメータにデータベース名をdb=sensor、SELECT文をq=SELECT * FROM sensorのように、URLエンコードして渡します。

$ curl 'http://localhost:8086/query?pretty=true&db=mydb' --data-urlencode 'q=SELECT * FROM sensor'

次のような応答が返ります。

{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "sensor",
                    "columns": [
                        "time",
                        "barometer",
                        "humidity",
                        "room",
                        "temperature"
                    ],
                    "values": [
                        [
                            "2020-08-18T10:27:19Z",
                            1023.4,
                            67.8,
                            "bedroom",
                            23.4
                        ],
                        [
                            "2020-08-18T10:28:19Z",
                            1023.3,
                            67.9,
                            "bedroom",
                            23.5
                        ]
                    ]
                }
            ]
        }
    ]
}

先ほど書き込んだデータが取得できていますね。 このように、デフォルトでHTTP APIが付属しているので、シェルスクリプトや任意のプログラミング言語から使いやすいです。 趣味の用途でDIYに使うのに、とても便利ですね。