PostgreSQLの時系列DB拡張TimescaleDBのマネージドサービスTimescale Cloud

[TimescaleDB](https://www.timescale.com/)はOSSのRDBMSのPostgreSQLの拡張機能の1つで、時系列データを扱いやすくするものです。
PostgreSQLに拡張を入れて有効化することで通常のRDBとしてのPostgreSQLを使いつつ、時系列データのパフォーマンスも向上してくれるものです。

仕組み的には、通常のテーブルに対してcreate_hypertableという関数を実行し、テーブル内の特定の時間を示すカラムをベースに細かいchunk(パーティションみたいなもの)に分割し、時間に沿ったデータの取り出しや登録を高速化するような仕組みになっているようです。

TimescaleDB自体はOSSで自前でPostgreSQLのサーバを構築して導入しても良いですが、マネージドなサービスであるTimescaleCloudというのも開発元が提供しているので、今回はこれを試しに使ってみます。

# Timescale Cloud

クラウドの最終的な稼働先としては、AWS、GCP、Azureのいずれかの上で動かすことになります。
この各IaaSクラウド環境上でTimescaleDBを動かして管理するのがTimescale Cloudです。
実態はAWS、GCP、Azure上にありますが、Timescale Cloudから使うと、特にその最終的な稼働先のことは意識せずに使えてしまいます。

[Timescale Cloud](https://www.timescale.com/cloud)

## アカウントの作成

https://www.timescale.com/cloud-signup

ここからサインアップ実施してアカウントを作成します。AWS、GCP、Azureのアカウントと連携させるとかは不要です。

## サービスの作成

Create Serviceからサービスを新規で作成します。

![timescale_cloud1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/5a6ece38-4fb4-0a16-c11b-a47d5c5cc9f6.png)


通常のTimescaleDBを選択し、AWSを稼働先として指定してみます。
プランが選べますが、まずは最小構成で試すため、Devのタイプを指定し、最も低価格のAWSのバージニアリージョンを選択して動かします。

![timescale_cloud2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/95b27395-76a6-322e-214c-a112a5f2298d.png)

これだけで作成は完了で、接続情報が払いだされます。

![timescale_cloud3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/203d6802-7265-b882-0eac-6ec44875aa38.png)

## psqlクライアントからつないでみる

psqlコマンドでつなぎにいける環境があれば上記サービスのDBにそのまま接続ができます。
今回はDockerコンテナをベースに立ち上げて接続確認してみます。

```
$ docker run --rm --name psql-client -it postgres:latest psql postgres://tsdbadmin:パスワード@tsd-xxxxxx.timescaledb.io:11116/defaultdb?sslmode=require

defaultdb=>
```

これで作成された環境に接続完了です。サービスの作成時にデフォルトでdefaultdbというデータベースが作成されます。

動作確認用に1つデータベース(timescalesampleという名前で)を追加してみます。

```
defaultdb=>CREATE DATABASE timescalesample;
defaultdb=>\l
 _timescaledb    | postgres  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 defaultdb       | tsdbadmin | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0       | postgres  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
                 |           |          |             |             | postgres=CTc/postgres
 template1       | postgres  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
                 |           |          |             |             | postgres=CTc/postgres
 timescalesample | tsdbadmin | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
```

## 通常のRDBのテーブルと時系列DBを作ってみる

冒頭でも書きましたが、timescaledbは通常のRDBのテーブルに対して、create_hypertableを実行することで、指定のタイムスタンプを示すカラムに合わせてchunk分割されたハイパーテーブルが作成されます。
そのため、まずは通常のRDBテーブルを作成し、その後ハイパーテーブルを作成すればOKです。

通常のテーブル作成

```
defaultdb=>\c timescalesample
timescalesample=> CREATE TABLE normal ( time TIMESTAMPTZ NOT NULL, value DOUBLE PRECISION  NOT NULL );
```

時系列データ用のテーブル作成

```
timescalesample=> CREATE TABLE timeseries ( time TIMESTAMPTZ NOT NULL, value DOUBLE PRECISION  NOT NULL );　←ここまでは同じ
timescalesample=> SELECT create_hypertable('timeseries', 'time');
```

この時、後から作成したtimescalesampleのデータベースではtimescaledbの拡張が有効になっていないため、create_hypertableの関数が使えないエラーが出るかと思います。
そこで事前に以下のようにCREATE EXTENSIONコマンドを実行しておく必要があります。

なお、デフォルトで作成されるdefaultdbは、最初からextensionが有効化された状態で動くようです。

```
timescalesample=> select * from pg_extension;
 14393 | plpgsql |       10 |           11 | f              | 1.0        |           | 

timescalesample=> CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
WARNING:  
WELCOME TO
 _____ _                               _     ____________
|_   _(_)                             | |    |  _  \ ___ \
  | |  _ _ __ ___   ___  ___  ___ __ _| | ___| | | | |_/ /
  | | | |  _ ` _ \ / _ \/ __|/ __/ _` | |/ _ \ | | | ___ \
  | | | | | | | | |  __/\__ \ (_| (_| | |  __/ |/ /| |_/ /
  |_| |_|_| |_| |_|\___||___/\___\__,_|_|\___|___/ \____/
               Running version 1.7.1
For more information on TimescaleDB, please visit the following links:

 1. Getting started: https://docs.timescale.com/getting-started
 2. API reference documentation: https://docs.timescale.com/api
 3. How TimescaleDB is designed: https://docs.timescale.com/introduction/architecture

Note: TimescaleDB collects anonymous reports to better understand and assist our users.
For more information and how to disable, please see our docs https://docs.timescaledb.com/using-timescaledb/telemetry.

Your license expires on 3019-01-01 00:00:00+00

CREATE EXTENSION
timescalesample=> select * from pg_extension;
 14393 | plpgsql     |       10 |           11 | f              | 1.0        |
            |
 17473 | timescaledb |       10 |         2200 | f              | 1.7.1      | {17490,17488,17514,17529,17527,17548,17546,17564,17562,17585,17601,17603,17619,17621,17639,17656,17692,17700,17729,17739,17749,17753,17770,17789,17804,17918,17924,17921} | {"","","","","","","","","","","","","","WHERE id >= 1000","","","WHERE key='exported_uuid'","","","","","","","","","","",""}
```


## データをINSERT

```
INSERT INTO normal (time, value) VALUES (current_timestamp, 123.456);
INSERT INTO timeseries (time, value) VALUES (current_timestamp, 123.456);
```

基本はどちらのテーブルでも同じ形で登録できます。SELECTするときも通常のテーブルも時系列用テーブルも同じ形で取得可能です。

## Timescale Cloudのバックアップ

マネージドサービスなので、バックアップとかも自動で取得してくれています。
ダッシュボード上で該当のサービスを選択し、Backupsのタブを選ぶと取得済みのバックアップのリストが表示されます。
Devプランの場合、1日1回取得されるようです。

![timescale_cloud4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/ffac3542-5bb8-243e-7fdc-923f9cb2a92b.png)


このページでRestoreを実行することができます。
Restoreボタンをクリックすると、バックアップデータを使って新たなサービスを作ってそこにインポートするための設定を行うことができるようです。
元のDBを巻き戻すのではなく、新たに作ってつなぎ先を切り替えるという方式での対応が必要となるようです。
リストアはPITR(ポイントインタイムリカバリ)なので、バックアップデータの取得時点まで巻き戻るというわけではなく、トランザクションログが残っている範囲のデータに対しては戻したい日時を指定してその時点まで戻した状態の新たなサービスが作られるようです。

なので、リストアの設定の「Source service state」の項目を「Latest transaction」を指定すると、直近のトランザクションの状態まで復元できます。

![timescale_cloud5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/b696d662-3183-afab-00ed-1382c2535862.png)

![timescale_cloud6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/5281f649-27d4-4012-6deb-53baa0204c46.png)


リストアされたデータの中身についてですが、
サービス作成時に作られるdefaultdbだけでなく、個別に作ったdatabaseも含めすべてリストアされています。

上記で作成したtimescalesampleのdatabaseおよびその中のnormalテーブル、timeseriesテーブルもすべてデータが移行されています。

```
timescalesample=> \d
            List of relations
 Schema |    Name    | Type  |   Owner
--------+------------+-------+-----------
 public | normal     | table | tsdbadmin
 public | timeseries | table | tsdbadmin
(2 rows)

timescalesample=> select * from normal;
             time              |  value
-------------------------------+---------
 2020-05-26 12:27:04.459953+00 | 123.456
(1 row)

timescalesample=> select * from timeseries;
             time              |  value
-------------------------------+---------
 2020-05-26 12:27:37.310907+00 | 123.456
 2020-05-27 10:14:44.745826+00 |     111
 2020-05-27 10:14:47.688243+00 |     112
 2020-05-27 10:14:50.438463+00 |     113
(4 rows)
```

## 監視情報やログ情報、クエリの実行統計情報

それ以外にも稼働状況のモニタリングデータやログ情報、クエリの実行統計情報などもダッシュボードから確認が可能です。

![timescale_cloud7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/410270c5-1dfd-cc52-172b-34eefef0c8a4.png)


![timescale_cloud8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45851/6f65831b-0f60-9c98-8c20-03717fa74ff1.png)


## 契約プランの違いと金額感について

Dev,Basic,Proの3プラン提供されていて、バックアップの管理の内容と可用性周りが一番大きな違いとしてあるようです。

Devプランの場合、バックアップは1日分のみ、Basicの場合は2日分、Proの場合3日分管理されるようです。
Dev,Basicはシングルノードで構成されるので何か問題があった場合は停止が発生します。
Proの場合は冗長構成が組まれて停止なしで運用できるようです。

あとは単純にIaaS上で直接作って管理する場合と比べて金額感としてどのぐらい違うかについては気になるところです。
Devプランの場合、AWSのEC2インスタンスでいうとt3.mediumとかに近い感じに見えます。(2coreCPU,4GBメモリ)
プラス20GBのディスクがついているといった感じです。

単純にAWSの金額にすると、t3.mediumをバージニアリージョンで立てると1か月で約3000円ちょっとぐらい、+EBSの料金も加算しても、4000円いかないぐらいかと思います。
それに対して、Timescale Cloudから起動した場合(Devプラン、バージニアリージョンの場合)に約6000円/月となるようなので多少金額は上乗せがかかります。
バックアップ管理、モニタリングなど管理の手間を考慮すると、この金額感なら良いような気がします。

ちなみに、RDSのバージニアリージョン、シングル配置のdb.t3.mediumのインスタンスを30日24時間稼働させると約5300円/月ぐらいはかかるのでこの金額とほぼ同じぐらいかと思います。


## まとめ

手軽にマネージドで使えて中身としては特に制約なく自由に使えるTimescaleDB拡張のPostgreSQLという感じです。
本番環境等で停止時間の許容が厳しい場合にはProプランの契約が必要になるので多少高額になることが見込まれるので要件・予算との兼ね合いで検討の余地はあるかと思います。
AWSのRDS上では2020/5時点ではtimescaledbの拡張には対応していないようなので、マネージドなTimescaleDBを使うならこの辺りを使うのが良いのかと思います。
https://github.com/timescale/timescaledb/issues/65

(AWSの場合はTimestreamというサービスも出てきているのでAWS上で作るだけならそういったサービスを検討するのが良いのかもしれないですが、特定のクラウドに縛られずに構築したいといったケースではTimescale Cloudもありかと思います。)