環境

PotgreSQL 13
TimescaleDB 2.4.2

対象のテーブルの圧縮を有効にする

まずはじめにhypertable化している対象のテーブルの圧縮を有効化します。ちなみに、hypertable可というのは、PostgreSQLのテーブルを時系列テーブルとして扱う場合にhypertableという形式に変換して利用します。圧縮の有効化は ALTER TABLE で行います。

ALTER TABLE iot_data SET (timescaledb.compress,timescaledb.compress_segmentby = 'sensor_id');
> Query 1 OK: ALTER TABLE

手動での圧縮

圧縮するチャンクの絞り込み

次に、show_chunks()使い、圧縮対象のチャンクを絞り込みを行います。チャンクに関して詳しく説明はしませんが、時系列データを詰め込む箱のようなもので1hypertalbeにつき複数存在します。クエリを実行すると以下のようにチャンク名が返るので控えてしてください。

-- 14日以前のデータが入ったチャンク名を取得する
SELECT show_chunks('iot_data', older_than => INTERVAL '14 days');
> _timescaledb_internal._hyper_19_210_chunk
> _timescaledb_internal._hyper_19_211_chunk
> ...
> ...

圧縮クエリの実行

前工程で控えたチャンク名を元に以下のクエリを発行すると圧縮が行われます。ある程度データが溜まっている状態で圧縮する場合、時間がかかるので気長に待ちましょう。圧縮が行われたかどうかは chunk_compression_stats() で確認できます。

-- 圧縮を行うクエリ
SELECT compress_chunk('_timescaledb_internal._hyper_19_210_chunk');

-- チャンクが圧縮されているか確認するクエリ
SELECT * FROM chunk_compression_stats('iot_data')

ポリシーによる圧縮の自動化

ポリシーを定めて、一定時間経過したデータを自動で圧縮する機能も存在します。

-- 14日以前のデータを自動圧縮するポリシーの登録
SELECT add_compression_policy('iot_data', INTERVAL '14 days');

-- 設定された圧縮ポリシーの削除
SELECT remove_compression_policy('iot_data');

圧縮で何が変わるのか

メリット

  • ディスク容量が節約できる
    hypertable_compression_stats() で テーブル単位の圧縮情報が確認できます。手元のデータでは 73.1GB → 1.93GB のディスク容量変化を確認できた。

  • 検索の速度の向上?
    ドキュメントによるとクエリによっては速度改善が望めるとあり期待していましたが、手元で試したクエリでは、恩恵を受けることはなく、改善も劣化も見られませんでした。どのようなクエリの場合に恩恵を受けるのか知りたいところです。

デメリット

  • 更新・削除が困難
    圧縮した状態では更新と削除が実行できず、更新するためにはチャンク単位で圧縮を解除する必要があり、これには多大にコストがかかります。テストで更新クエリを投げてみましたが cannot update/delete rows from chunk "_hyper_19_210_chunk" as it is compressed となり失敗しました。

    また、追加も一部のみサポートとドキュメントにあり、テストでクエリを実行しましたが insert into a compressed chunk that has primary or unique constraint is not supported となって失敗しました。このバージョンではプライマリーキーもしくはユニークキーが設定されたテーブルは挿入もできないようです。

    このあたりは次期バージョンでできるようになっていって欲しいところです。

参考

Compression
https://docs.timescale.com/api/latest/compression/
Hypertable & Chunks
https://docs.timescale.com/api/latest/hypertable/