PostgreSQL拡張機能「TimescaleDB」を使ってみた(導入編)


こんにちは。SJC共同開発推進室の菊池です。
弊社はIoT関連の開発を多く手がけていることもあり、センサーから上がってくる大量の時系列データを保存するケースが多々あります。

今回、その保存先としてPostgreSQLを利用しようと考えており、大量の時系列データを効率よく管理できる方法を探していたところ、
「TimescaleDB」という拡張機能があることを知りましたのでご紹介します。

「TimescaleDB」導入の経緯

大量の時系列データを扱うならS3に置くべきか、いっそのことNoSQLにしてしまうべきか、色々と検討しましたが、
すでにマスタデータの管理などでPostgreSQLを使っており、既存のアプリケーションもそれに合わせて動いています。
諸々状況を考慮した結果、インフラコストの観点を最優先とし、現状のシステム構成に手を加えずに済むPostgreSQLでの保存を選択しました。

しかし懸念となるのが、大量の時系列データを扱う場合のパフォーマンスです。
もちろんインデックスを張るだけでもかなりの効果は期待できますが、今回はさらに上のパフォーマンスを目指したい。
その手段として行き着いたのが「パーティショニング」の導入でした。

パーティショニングとは、1つの巨大なテーブルを日付などの条件で複数の小さなテーブルに分割し、必要なデータだけを効率よく扱うためのPostgreSQLの標準機能です。
例えば、以下のように設定することで、日付ごとにデータをパーティショニングできます。

このようにあらかじめデータを時間で分割しておくと、特定の期間を検索する際、
関係のない子テーブルへの無駄なディスクI/Oを完全に排除してSELECTできるため、処理が高速化するという仕組みです。
ですが、実際にシステムへ導入する場合、

  • パーティションを毎回手動で追加する
  • 自動作成するバッチを自前で組んで運用する

など、パーティショニングを維持するために自前で管理し続けなければならないという課題があります。
もし、不具合等でバッチが途中で停止したり、手動での追加を忘れたりした状態で、まだ作成していない日付のデータが流れ込むと、
DBエラーが発生してサービス全体が停止するリスクもあります…

TimescaleDBなら「データが来た瞬間にその場で自動生成」

TimescaleDBは、この「未来のパーティションテーブルを事前に手動で追加しなければいけない」という処理を自動で行ってくれるのが大きな特徴です
WSL(Ubuntu)環境を用いて、実際にTimescaleDBの環境を構築していきます。

1. インストールと初期設定

公式サイトを参考に、リポジトリの追加とインストールを行います。

2. 拡張機能の有効化とテーブル作成

データベースにログインして、初期設定を行います。

拡張機能を有効化し、「自動パーティショニング」機能を扱うためのテーブル「ハイパーテーブル(Hypertable)」を作成します。

例として30日間にまたがるテストデータを投入してみます。

この時、データがINSERTされたタイミングで、必要に応じて「チャンク(Chunk)」と呼ばれる物理テーブルが自動生成されます。
チャンクとは?
ハイパーテーブルの裏側で、TimescaleDBが自動生成する物理テーブルです。これが自動パーティションの実体となります。
参考:Hypertables and chunks
本当に裏側でチャンクが自動生成されているかは、TimescaleDB専用の show_chunks() 関数 を使うことで確認できます。

実行結果:

実際にデータを取得するときのSELECTは以下のように、「ハイパーテーブル」に対して、通常のPostgreSQLと全く同じようにクエリを投げるだけでOKです。

実行結果:

まとめ

今回はTimescaleDBの構築をメインに解説しました。
実際に触ってみると意外と簡単に設定でき、面倒なパーティション設定を自動で行ってくれる点は、
自前でパーティション設定するよりも非常に大きなメリットだと感じます。
(ただ、26年6月現在、Amazon RDSのPostgreSQLではTimescaleDBを使うことができないのが残念…)
次回は、実際にアプリケーションからどのように操作するかを検証してみたいと思います!

最後に

エコモットでは一緒にモノづくりをしていく仲間を募集中です。
弊社に少しでも興味がある方は、ぜひ下記の採用ページをご覧ください!