TimescaleDB の紹介

TimescaleDB は、IoT 機器のセンサーやスマートメーターが生成するデータのように、時系列に沿って発生するデータを扱うのに適した時系列データベースの機能を、リレーショナルデータベース PostgreSQL に追加する拡張モジュールです。

この記事では、TimescaleDB の概要とインストール、基本的な使い方について紹介します。

TimescaleDB とは

TimescaleDB は米国 Timescale 社 が開発する時系列データベースで、ソースコードは GitHub リポジトリ で公開されています。ライセンスは一部が Timescale ライセンス (TSL) で、それ以外は Apache ライセンス 2.0 です。TSL 部分は簡単に言えばそれ自体をサービスとして提供しない限り自由に使えます。ライセンスについて正確には自分で確認してください。

TimescaleDB は PostgreSQL の拡張モジュールとして実装されていて、リレーショナルデータベースと NoSQL の特長をあわせもちます。

  • 使いやすさ – SQL に完全対応をしていて、PostgreSQL 用のアプリケーションもそのまま接続でき、時系列データ向けの分析や管理機能も備えています。
  • スケーラビリティの高さ – データは適切なサイズに分割して格納され、データ量が増えても安定して高速に書き込みでき、並列処理にも対応しています。
  • 信頼性の高さ – 長い歴史をもつ PostgreSQL 上で動作し、レプリケーションやバックアップなど、PostgreSQL の機能はもちろん、PostgreSQL 用のツールも使えます。

TimescaleDB では、データは内部的に時間と空間で分割されたチャンクと呼ばれるテーブルに格納され、ハイパーテーブルを介して透過的にアクセスされます。空間は時間以外にチャンクを分割する条件です。分割方式として 継承によるパーティショニング を採用していて、複数の条件で分割しても階層が多段にならない実装になっています。

TimescaleDB のアークテクチャ

TimescaleDB のインストール

TimescaleDB は各プラットフォーム向けのバイナリに加え、Docker イメージや AMI、マネージドサービス Timescale Cloud も提供されています。すべてのインストール方法については TimescaleDB DocumentationInstallation を参照してください。

TimescaleDB は 2021 年 6 月時点で以下のバージョンがメンテナンスされていて、それぞれ対応する PostgreSQL のバージョンが異なります。

TimescaleDB バージョン 対応 PostgreSQL バージョン
2.4以降 12、13
2.1~2.3 12、13
2.0 11、12
1.7 9.6、10、11、12

ここでは、CentOS 8 上の PostgreSQL 13 に Yum を使って TimescaleDB をインストールしていきます。

  1. TimescaleDB の Yum リポジトリを登録します。

    $ sudo tee /etc/yum.repos.d/timescale_timescaledb.repo <<EOF
    [timescale_timescaledb]
    name=timescale_timescaledb
    baseurl=https://packagecloud.io/timescale/timescaledb/el/\$releasever/\$basearch
    repo_gpgcheck=1
    gpgcheck=0
    enabled=1
    gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
    sslverify=1
    sslcacert=/etc/pki/tls/certs/ca-bundle.crt
    metadata_expire=300
    EOF
    
  2. TimescaleDB の RPM パッケージをインストールします。

    $ sudo yum -y install timescaledb-2-postgresql-13
    (省略)
    Installed:
      timescaledb-2-postgresql-13.x86_64 0:2.2.0-0.el8
    
    Dependency Installed:
      timescaledb-2-loader-postgresql-13.x86_64 0:2.2.0-0.el8
      timescaledb-tools.x86_64 0:0.11.0-0.el8
    
    Complete!
    
  3. TimescaleDB 向けに PostgreSQL の設定を行います。

    設定ファイル postgresql.conf を直接編集してもよいですが、ここでは、メモリ量や CPU 数をもとに対話的に設定を行う timescaledb-tune コマンドを使います。

    $ sudo timescaledb-tune --pg-config=/usr/pgsql-13/bin/pg_config
    Using postgresql.conf at this path:
    /var/lib/pgsql/13/data/postgresql.conf
    
    Is this correct? [(y)es/(n)o]: y
    Writing backup to:
    /tmp/timescaledb_tune.backup202105010056
    
    shared_preload_libraries needs to be updated
    Current:
    #shared_preload_libraries = ''
    Recommended:
    shared_preload_libraries = 'timescaledb'
    Is this okay? [(y)es/(n)o]: y
    success: shared_preload_libraries will be updated
    
    Tune memory/parallelism/WAL and other settings? [(y)es/(n)o]: y
    Recommendations based on 465.21 MB of available memory and 1 CPUs for PostgreSQL 13
    
    Memory settings recommendations
    Current:
    shared_buffers = 128MB
    #effective_cache_size = 4GB
    #maintenance_work_mem = 64MB
    #work_mem = 4MB
    Recommended:
    shared_buffers = 119094kB
    effective_cache_size = 357282kB
    maintenance_work_mem = 59547kB
    work_mem = 2977kB
    Is this okay? [(y)es/(s)kip/(q)uit]: y
    success: memory settings will be updated
    
    WAL settings recommendations
    Current:
    #wal_buffers = -1
    min_wal_size = 80MB
    Recommended:
    wal_buffers = 3572kB
    min_wal_size = 512MB
    Is this okay? [(y)es/(s)kip/(q)uit]: y
    success: WAL settings will be updated
    
    Miscellaneous settings recommendations
    Current:
    #default_statistics_target = 100
    #random_page_cost = 4.0
    #checkpoint_completion_target = 0.5
    max_connections = 100
    #max_locks_per_transaction = 64
    #autovacuum_max_workers = 3
    #autovacuum_naptime = 1min
    #effective_io_concurrency = 1
    Recommended:
    default_statistics_target = 500
    random_page_cost = 1.1
    checkpoint_completion_target = 0.9
    max_connections = 20
    max_locks_per_transaction = 64
    autovacuum_max_workers = 10
    autovacuum_naptime = 10
    effective_io_concurrency = 200
    Is this okay? [(y)es/(s)kip/(q)uit]: y
    success: miscellaneous settings will be updated
    Saving changes to: /var/lib/pgsql/13/data/postgresql.conf
    

    --pg-config オプションには pg_config コマンドのパスを指定します。そのほかのオプションは --help オプションで確認できます。実行を開始すると、次々に聞かれる質問に答えていきます。基本的には y を入力していけばよいです。最後に設定がファイルに書き込まれます。

  4. 設定を反映するため、PostgreSQL のサービスを再起動します。

    $ sudo systemctl restart postgresql-13
    
  5. TimescaleDB の拡張モジュールをデータベースにインストールします。

    ここでは、PostgreSQL のスーパーユーザ postgres に切り替わり、テスト用に test データベースを作成し、そこにインストールします。

    $ sudo su - postgres
    $ createdb test
    $ psql -c "CREATE EXTENSION timescaledb" test
    WARNING:
    WELCOME TO
     _____ _                               _     ____________
    |_   _(_)                             | |    |  _  \ ___ \
      | |  _ _ __ ___   ___  ___  ___ __ _| | ___| | | | |_/ /
      | | | |  _ ` _ \ / _ \/ __|/ __/ _` | |/ _ \ | | | ___ \
      | | | | | | | | |  __/\__ \ (_| (_| | |  __/ |/ /| |_/ /
      |_| |_|_| |_| |_|\___||___/\___\__,_|_|\___|___/ \____/
                   Running version 2.2.0
    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.
    
    CREATE EXTENSION
    

TimescaleDB の基本的な使い方

ここからは、test データベースに接続し、TimescaleDB の基本的な使い方を確認していきます。

$ psql test
psql (13.2)
"help"でヘルプを表示します。

=#

ハイパーテーブルの作成

ハイパーテーブルを作成するには通常のテーブルを作成し、create_hypertable 関数を実行します。ここでは、時間と場所ごとに温度と湿度を格納する conditions テーブルを作成し、ハイパーテーブルに変換します。

=# CREATE TABLE conditions (
     time timestamp NOT NULL,
     location text NOT NULL,
     temperature double precision,
     humidity double precision
   );
CREATE TABLE
=# SELECT create_hypertable('conditions', 'time');
    create_hypertable
-------------------------
 (1,public,conditions,t)
(1 行)

create_hypertable 関数の引数にはハイパーテーブルに変換するテーブル名、分割の条件にする時間の列名を指定します。戻り値はそれぞれハイパーテーブルの ID、スキーマ名、テーブル名、実際に作成されたかが返されます。

チャンクはデフォルトで 7 日ごとに分割されます。時間列のデータ型はタイムスタンプや日付以外に整数にも対応しています。整数の場合には値が表す時間の大きさが分からないため、チャンクを分割する間隔を chunk_time_interval 引数で指定する必要があります。例えば、時間列が秒を表し、7 日ごとに分割する場合には、7 日 × 24 時間 × 60 分 × 60 秒 = 604,800 を指定します。

(以下、例示のため、実行不要)
=# SELECT create_hypertable('conditions', 'time');
ERROR:  integer dimensions require an explicit interval
=# SELECT create_hypertable('conditions', 'time', chunk_time_interval := 604800);
    create_hypertable
-------------------------
 (1,public,conditions,t)
(1 行)

変換元のテーブルは空でないとエラーになります。migrate_data 引数に true を指定すれば、データを移行することもできます。データ量が多いと時間がかかり、外部キー制約があるとデッドロックが発生する可能性があります。通常はハイパーテーブルの作成後にデータを投入したほうがよいでしょう。

(以下、例示のため、実行不要)
=# SELECT create_hypertable('conditions', 'time');
ERROR:  table "conditions" is not empty
HINT:  You can migrate data by specifying 'migrate_data => true' when calling this function.
=# SELECT create_hypertable('conditions', 'time', migrate_data := true);
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
    create_hypertable
-------------------------
 (1,public,conditions,t)
(1 行)

create_hypertable 関数について詳しくは TimescaleDB Documentation の API Reference を参照してください。

時系列データの操作

時系列データの操作はハイパーテーブルを介して通常のデータと同じようにできます。ここでは、まず、データの挿入、検索、更新、削除をしてみます。

=# INSERT INTO conditions
     VALUES ('2021-05-01 09:00:00', 'tokyo', 19.4, 62.0);
INSERT 0 1
=# SELECT * FROM conditions;
        time         | location | temperature | humidity
---------------------+----------+-------------+----------
 2021-05-01 09:00:00 | tokyo    |        19.4 |       62
(1 行)

=# UPDATE conditions
   SET temperature = temperature + 0.1
   WHERE time = '2021-05-01 09:00:00'
     AND location = 'tokyo';
UPDATE 1
=# DELETE FROM conditions
   WHERE time = '2021-05-01 09:00:00'
     AND location = 'tokyo';
DELETE 1

次に、あとで分析に使うデータを生成します。データは 2020 年 1 月 1 日から 1 分間隔で 1 年間、場所は東京、名古屋、大阪の 3 か所、温度は 10 〜 30 度、湿度は 60 〜 90% の範囲でランダムです。これで 55 個のチャンクからなる 1,581,120 行、135MB のデータになります。データの投入後は ANALYZE コマンドで統計情報を更新しておきましょう。

=# INSERT INTO conditions
   SELECT time,
     location,
     round(10 + random()::numeric * (30 - 10), 1) AS temperature,
     round(60 + random()::numeric * (90 - 60), 0) AS humidity
   FROM generate_series('2020-01-01 00:00:00'::timestamp, '2020-12-31 23:59:00', '1 minute') AS time,
     unnest(ARRAY['tokyo', 'nagoya', 'osaka']) AS location;
INSERT 0 1581120
=# ANALYZE;
ANALYZE

チャンクの削除

データの削除は DELETE コマンドでもできますが、それだと不要領域が発生し、回収して再利用可能にするにはバキュームが必要です。それに対して、チャンクごと削除すれば、不要領域が発生せずに済みます。

チャンクを削除するには drop_chunks関数を実行します。ここでは、2021 年 2 月 1 より前のチャンクを削除します。

=# SELECT drop_chunks('conditions', '2020-02-01 00:00:00'::timestamp);
              drop_chunks
----------------------------------------
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_3_chunk
 _timescaledb_internal._hyper_1_4_chunk
 _timescaledb_internal._hyper_1_5_chunk
 _timescaledb_internal._hyper_1_6_chunk
(5 行)

drop_chunks 関数の引数にはハイパーテーブルの名前、いつより前のデータしか含まないチャンクを削除するかのタイムスタンプを指定します。戻り値は削除されたチャンクの名前が返されます。

いつより前を削除するかはタイムスタンプや日付、整数以外に間隔にも対応しています。間隔の場合には現在を基準にその間隔より前が削除されます。例えば、現在が 2021 年 5 月 1 日で、間隔が 15 か月の場合には、2020 年 2 月 1 日より前のチャンクが削除されます。

(以下、例示のため、実行不要)
=# SELECT drop_chunks('conditions', '15 months'::interval);
              drop_chunks
----------------------------------------
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_3_chunk
 _timescaledb_internal._hyper_1_4_chunk
 _timescaledb_internal._hyper_1_5_chunk
 _timescaledb_internal._hyper_1_6_chunk
(5 行)

drop_chunks 関数について詳しくは TimescaleDB Documentation の API Reference を参照してください。

おわりに

今回は、リレーショナルデータベースと NoSQL の特長をあわせもった時系列データベース TimescaleDB の概要、CentOS 8 上の PostgreSQL 13 への Yum を使ったインストール、ハイパーテーブルの作成や時系列データの操作など、基本的な使い方について紹介しました。

次回は、TimescaleDB の備える時系列データ向けの分析機能について紹介します。