GanosBase TSDB は、PolarDB for PostgreSQL の拡張機能として提供される時系列データベースサービスです。 GanosBase TSDB は、共有ストレージ、1 つのプライマリノードと複数の読み取り専用ノード、バックアップとリストアなど、PolarDB for PostgreSQL クラスタのすべての機能を継承しています。 GanosBase TSDB は Apache 2.0 と互換性があり、継続的集計、圧縮、時系列データの統計分析などの高度な機能を提供します。 このトピックでは、時系列データベースの用語と、GanosBase TSDB の使用方法 (GanosBase TSDB の起動、スペックアップ、使用方法を含む) について説明します。
前提条件
PolarDB for PostgreSQL クラスタは、リビジョンバージョン 2.0.14.13.26.0 以降の PolarDB for PostgreSQL 14 を実行しています。
PolarDB コンソールから、または SHOW polardb_version;
文を実行することで、クラスタのリビジョンバージョンを確認できます。 クラスタのリビジョンバージョンが要件を満たしていない場合は、リビジョンバージョンをスペックアップしてください。
用語
時系列データ: 時系列で記録されたデータを指します。 このデータタイプの特性は、データポイントに数値情報が含まれているだけでなく、特定のタイムスタンプにも関連付けられており、時間の経過に伴う変数の傾向やパターンを反映していることです。 時系列データは、金融取引、気象観測、センサー監視、Web トラフィック分析、疾病伝播調査など、多くの分野で広く使用されています。 時系列データの主要な要素は次のとおりです。
タイムスタンプ: 各データポイントには、データがいつ収集されたかを示す明確なタイムスタンプがあります。
観測値: さまざまな時点で測定または記録されたデータ値。
順序性: データポイントは時系列で配置され、データポイント間の時間関係と時系列の特性を反映しています。
傾向と周期性: 時系列データ分析では、多くの場合、長期的な傾向、季節変動、循環的変化、データのランダムな変動に焦点を当てます。
メトリック: 温度、株価、ネットワークトラフィックなど、定量化および測定できる監視メトリック。 メトリックは、時系列データの動作パターンの描写、将来の傾向の予測、異常のタイムリーな発見と対応に役立ちます。
集約: 時系列データ分析において、高頻度データを低頻度データと集約するプロセス。 データは時間ディメンションでマージまたは集約され、データの主要な傾向または特性を維持しながら、データの粒度が減少します。 このアプローチは、データの次元削減、傾向分析、異常検出、予測モデルの構築に役立ちます。
ダウンサンプリング: 時系列データのサンプリング周波数 (またはデータポイントの数) を減らし、生データのコア機能または傾向を維持できます。 時系列のダウンサンプリングには、次の方法がよく使用されます。
間引き: これは最も簡単な方法です。N ポイントごとにデータポイントを取得します。 たとえば、元のシーケンスが 1 秒あたり 10 回サンプリングされる場合、5 つのデータポイントごとに最初の 1 つだけを保持することで、1 秒あたり 2 回のサンプリングを実現できます。 この方法は簡単ですが、高周波数情報が失われる可能性があります。
平均化: ダウンサンプリングの前に、連続するデータポイントを平均化します。 たとえば、連続する 5 つのデータポイントを平均して、新しいデータポイントを取得します。 この方法では、データを平滑化してノイズを低減できますが、変化する詳細が不明瞭になる場合があります。
中央値: この方法は平均化の方法に似ていますが、平均ではなく連続するデータポイントの中央値を使用します。 外れ値を含む時系列を扱う場合、より堅牢です。
最大値または最小値: 連続するデータポイントの中で最大値または最小値を新しいデータポイントとして選択します。 この方法は、ピーク値またはボトム値を保持する必要があるシナリオに適用できます。
リサンプリング: 補間などの方法を使用してデータを新しい時点に調整し、新しいタイムラインで均一サンプリングを実行します。 一般的なリサンプリング方法には、線形補間、最近傍補間、3 次補間などがあります。 リサンプリング方法は柔軟性があり、元のデータ形式を維持しながら、任意のサンプリング周波数に調整できます。
モデル予測ダウンサンプリング: 統計モデルまたは機械学習モデルを使用して、低いサンプリングレートでデータポイントを予測します。 たとえば、ARIMA や LSTM などのモデルを使用して、新しい各時点の値を予測し、これらの予測値をダウンサンプリング後のデータとして使用できます。 この方法はよりインテリジェントにダウンサンプリングを実装しますが、計算コストが高くなります。
比較GanosBase TSDB と TimescaleDB の
TimescaleDB: PostgreSQL 上に構築されたオープンソースの時系列データベースであり、センサーの読み取り値、監視メトリック、財務データなどの時系列データを管理するために最適化されています。 PostgreSQL の完全な SQL 機能を保持し、時系列データに対して効率的なストレージ、高速書き込み、複雑なクエリ機能を提供します。
GanosBase TSDB: TimescaleDB 上に開発された時系列エンジン。 PolarDB for PostgreSQL クラスタの拡張機能として提供され、共有ストレージ、1 つのプライマリノードと複数の読み取り専用ノード、バックアップとリストアなど、PolarDB のすべての機能を継承しています。
違い
GanosBase TSDB と TimescaleDB の主な違いは機能です。 TimescaleDB Apache 2 Edition は、ユーザーがソースコードを使用または変更できるオープンソースライセンスである Apache 2.0 ライセンスでリリースされています。 ただし、このエディションは基本機能のみを提供します。
GanosBase TSDB は、TimescaleDB が提供する基本機能に加えて、継続的集計、データ圧縮、コールドホット階層型ストレージなどの高度な機能を提供します。
GanosBase TSDB を有効にする
PolarDB for PostgreSQL クラスタで GanosBase TSDB を有効にするには、timescaledb
を shared_preload_libraries パラメータに追加する必要があります。 PolarDB コンソールで shared_preload_libraries パラメータを変更できます。
shared_preload_libraries パラメータを変更すると、クラスタが再起動します。 注意して進めてください。
拡張機能をインストールする
拡張機能をスペックアップする
時系列ハイパーテーブル
ハイパーテーブルは、時系列データベースで提供される特別なテーブルタイプです。 時系列データを簡単に処理できます。 通常のテーブルで実行できるすべての操作は、ハイパーテーブルで実行できます。
機能
ハイパーテーブルは、PolarDB for PostgreSQL のデータテーブルであり、時間によってデータを自動的にパーティション分割するために使用できます。 ハイパーテーブルは通常のテーブルと同じ方法で操作されますが、ハイパーテーブルには、時系列データの管理を容易にする追加機能もいくつかあります。
時系列データベースでは、ハイパーテーブルは通常のテーブルと共存します。 ハイパーテーブルを使用して時系列データを格納できます。 これにより、データの書き込みとクエリの パフォーマンスが向上し、ハイパーテーブルでシーケンス関数を使用できるようになります。
時系列データベースは、時間パラメータに基づいてハイパーテーブルの時系列データをパーティション分割できます。 バックグラウンドでは、時系列データベースがハイパーテーブルパーティションを自動的に構成および維持します。
ハイパーテーブルを作成する
次の文を実行して、通常のテーブルをハイパーテーブルに変換します。
SELECT create_hypertable(
'table_name',
'time_column_name',
'partitioning_column_name',
number_partitions,
'associated_schema_name',
'associated_table_prefix',
chunk_time_interval,
create_default_indexes,
if_not_exists,
partitioning_func,
migrate_data,
chunk_target_size,
chunk_sizing_func,
time_partitioning_func
);
次の表にパラメータを示します。
パラメータ | 必須 | 説明 |
table_name | はい | 通常のテーブルの名前または OID。 通常のテーブルとハイパーテーブルを区別するために、前者は元のテーブルと呼ばれます。 変換されたハイパーテーブルの名前は、元のテーブルと同じです。 |
time_column_name | はい | 元のテーブルで時系列特性を持つ時間列の名前。 次のデータ型がサポートされています。
|
partitioning_column_name | いいえ | パーティション分割された列の名前。 デフォルトでは、ハイパーテーブルは元のテーブルの時間フィールドに基づいてパーティション分割されます。 |
number_partitions | いいえ | パーティションの数。 |
associated_schema_name | いいえ | ハイパーテーブルのスキーマ。 |
associated_table_prefix | いいえ | ハイパーテーブルは複数のチャンクで構成され、システムによって自動的に作成されます。 チャンクのプレフィックスを指定できます。 |
chunk_time_interval | いいえ | ハイパーテーブルがチャンクに分割される間隔。 デフォルト値は 7 日です。 |
create_default_indexes | いいえ | ハイパーテーブルの時間列に B-Tree インデックスを作成するかどうかを指定します。 有効な値:
|
if_not_exists | いいえ | ハイパーテーブルが作成された場合にエラーを返すかどうかを指定します。 有効な値:
|
partitioning_func | いいえ | 空間パーティション分割を使用する場合、カスタム空間パーティション分割関数を指定できます。 |
migrate_data | いいえ | 元のテーブルに既にデータがある場合に、データをハイパーテーブルに転送するかどうかを指定します。 有効な値:
|
chunk_target_size | いいえ | チャンクのサイズ (例: |
chunk_sizing_func | いいえ | チャンキング間隔をカウントするために使用されるカスタム関数。 このパラメータは、 |
time_partitioning_func | いいえ | 時間パーティションに使用されるパーティション分割関数。 |
ハイパーテーブルのパーティション
ハイパーテーブルを作成して使用すると、時間または空間によってデータが自動的にパーティション分割されます。
各ハイパーテーブルは複数のチャンクで構成されます。 各チャンクには時間範囲が割り当てられており、その時間範囲内のデータのみが含まれています。 ハイパーテーブルも空間によってパーティション分割されている場合、各チャンクには空間値のサブセットも割り当てられます。
ハイパーテーブルの各ブロックには、特定の時間範囲内のデータのみが含まれています。 既存のチャンクに割り当てられていない時間範囲にデータを挿入すると、チャンクが自動的に作成されます。
デフォルトでは、ハイパーテーブルは 7 日間隔でパーティション分割されます。 また、次の SQL 文を実行して、パーティション分割間隔を変更することもできます。
SELECT set_chunk_time_interval(
'table_name',
chunk_time_interval,
'dimension_name'
);
次の表にパラメータを示します。
パラメータ | 説明 |
table_name | ハイパーテーブルの名前。 |
chunk_time_interval | ハイパーテーブルがチャンクに分割される間隔。 |
dimension_name | オプション。 パーティション分割 (ディメンション) ポリシー。 デフォルト値: NULL。 |
例
トランザクションデータを格納するハイパーテーブルを作成します。
通常のテーブルを作成します。
CREATE TABLE transaction_data( tm TIMESTAMPTZ NOT NULL, id INT NOT NULL, price double precision);
通常のテーブルのレプリケーション識別子を設定します。これは DEFAULT である必要があります。
ALTER TABLE transaction_data replica IDENTITY DEFAULT;
通常のテーブルをハイパーテーブルに変換します。
SELECT create_hypertable('transaction_data', 'tm', chunk_time_interval => INTERVAL '1 day');
説明テーブルに既にデータが含まれている場合は、
migrate_data
パラメータを含めてtrue
に設定し、既存のデータをハイパーテーブル構造に移行する必要があります。 テーブルに大量のデータが含まれている場合、この移行プロセスにはかなりの時間がかかる場合があります。(オプション) ハイパーテーブルのパーティション分割間隔を変更します。
SELECT set_chunk_time_interval('transaction_data', chunk_time_interval => INTERVAL '2 day');
継続的集計
継続的集計は、時間平均などの事前定義された集計結果を定期的にまたは継続的に更新するように設計された自動事前計算メカニズムです。 これらの集計を毎回最初から再計算する代わりに、クエリは事前計算された結果に直接アクセスできるため、データ取得がより迅速かつ効率的になります。 従来のマテリアライズドビューとは異なり、継続的集計は時系列データ向けに特に最適化されており、増分更新をサポートしています。 更新中は、新規または変更されたデータのみが処理されるため、データセット全体を再計算する必要はありません。 このアプローチにより、計算オーバーヘッドが大幅に削減され、大規模なデータセットに対するクエリが高速化されます。
メリット:
クエリの高速化: 継続的集計により、事前計算された結果を直接クエリできるため、生データの全表スキャンが不要になります。
リソースの節約: その場で再計算を回避することにより、継続的集計は CPU とメモリリソースの消費を大幅に削減します。
自動メンテナンス: 継続的集計は、手動介入なしで、新規データと既存データの両方の更新を自動的に管理します。
継続的集計を作成する
CREATE MATERIALIZED VIEW transaction_min_cagg
WITH (timescaledb.continuous) -- マテリアライズドビューを継続的集計として宣言します。
AS
SELECT id,
time_bucket(INTERVAL '1 min', tm) AS bucket, -- データを 1 分間隔でグループ化します。
AVG(price),
MAX(price),
MIN(price)
FROM transaction_data
GROUP BY id, bucket;
継続的集計結果を格納する
継続的集計の結果は、専用の マテリアライズドビューに格納され、データは時間ベースのチャンクに編成されます。 これらのチャンクは、基になるハイパーテーブルデータのパーティション分割に一致します。
タスクスケジューリング
継続的集計は、タスクスケジューリングメカニズムを使用して、集計結果が自動または手動でリフレッシュされるようにします。
ジョブを作成する
定義された間隔で関数またはストアドプロシージャを呼び出す ジョブを作成します。
integer add_job(
proc REGPROC,
schedule_interval INTERVAL,
config JSONB DEFAULT NULL,
initial_start TIMESTAMPTZ DEFAULT NULL,
scheduled BOOL DEFAULT true,
check_config REGPROC DEFAULT NULL,
fixed_schedule BOOL DEFAULT TRUE,
timezone TEXT DEFAULT NULL
);
パラメータ:
パラメータ | 説明 |
proc | ジョブによって実行される関数またはストアドプロシージャの名前または OID。 |
schedule_interval | ジョブを実行する間隔。 |
config | ジョブの構成パラメータ。 |
initial_start | ジョブの最初の開始時刻。 デフォルトでは、ジョブは作成時に開始されます。 |
scheduled | ジョブが自動的に実行されるようにスケジュールされているかどうかを指定します。 デフォルト: |
check_config |
|
fixed_schedule | ジョブが指定された間隔で実行されるかどうかを指定します。 デフォルト: |
timezone | タイムゾーン。 デフォルト: NULL。 |
例
ジョブによって実行されるストアドプロシージャを作成します。
CREATE OR REPLACE PROCEDURE user_defined_action(job_id int, config jsonb) LANGUAGE PLPGSQL AS $$ BEGIN RAISE NOTICE 'Executing action % with config %', job_id, config; -- 操作 % を構成 % で実行しています END $$;
add_job
関数を使用して、ジョブを定期的に実行するようにスケジュールします。add_job
を呼び出すたびに新しいジョブが作成され、一意のジョブ ID が返されます。SELECT add_job('user_defined_action','1 hour'); SELECT add_job('user_defined_action','1h', initial_start => '2024-03-11 00:00:00');
ジョブを変更する
既存のジョブを変更します。
void alter_job( job_id INTEGER,
schedule_interval INTERVAL = NULL,
max_runtime INTERVAL = NULL,
max_retries INTEGER = NULL,
retry_period INTERVAL = NULL,
scheduled BOOL = NULL,
config JSONB = NULL,
next_start TIMESTAMPTZ = NULL,
if_exists BOOL = FALSE,
check_config REGPROC = NULL,
fixed_schedule BOOL = NULL,
initial_start TIMESTAMPTZ = NULL,
timezone TEXT DEFAULT NULL
);
パラメータ:
次の表では、パラメータの一部のみについて説明します。 その他のパラメータの説明については、ジョブを作成する をご参照ください。
パラメータ | 説明 |
job_id | 変更するジョブの ID。 |
max_runtime | ジョブの実行が許可される最大時間。 デフォルト: NULL。 |
max_retries | ジョブが失敗した場合に許可される最大再試行回数。 デフォルト: NULL。 |
retry_period | ジョブが失敗した場合の再試行間隔。 デフォルト: NULL。 |
例
SELECT alter_job(1002, schedule_interval => INTERVAL '2 hours');
ジョブを手動で実行する
既存のジョブを手動で実行します。
void run_job(job_id int);
パラメータ:
パラメータ | 説明 |
job_id | 実行するジョブの ID。 |
例:
CALL run_job(1002);
ジョブを削除する
ジョブを削除します。
void delete_job(job_id int);
パラメータ:
パラメータ | 説明 |
job_id | 削除するジョブ |
例:
SELECT delete_job(1002);
継続的集計をリフレッシュする
継続的集計を手動でリフレッシュする
継続的集計を手動でリフレッシュします。
refresh_continuous_aggregate(
cagg REGCLASS,
window_start "any",
window_end "any"
);
パラメータ:
パラメータ | 説明 |
cagg | リフレッシュする継続的集計の名前または OID。 |
window_start | リフレッシュウィンドウの開始時刻。 データ型は、継続的集計で使用される時間フィールドと一致する必要があります。
|
window_end | リフレッシュウィンドウの終了時刻。 データ型は、継続的集計で使用される時間フィールドと一致する必要があります。 終了時刻が不明な場合は、このパラメータを |
使用上の注意
継続的集計は、固定された時間間隔で結果を事前計算するように設計されています。 継続的集計をリフレッシュする場合、リフレッシュウィンドウは集計の事前定義された間隔と一致する必要があります。 一致しない場合、部分的または不完全な間隔は無視されます。
リフレッシュウィンドウが重複する
refresh_continuous_aggregate
関数を複数回呼び出すと、重複する間隔は、それらの間隔に新しいデータまたは変更されたデータがある場合にのみ再計算されます。refresh_continuous_aggregate
はストアドプロシージャ関数です。 関数は、CALL 文を使用してのみ呼び出すことができます。
例
CALL refresh_continuous_aggregate('transaction_min_cagg', '2024-03-11 00:00:00+08'::timestamptz, NULL);
継続的集計のリフレッシュを自動化する
次のいずれかの方法を使用して、継続的集計のリフレッシュを自動化できます。
add_continuous_aggregate_policy 関数を使用する
リアルタイムクエリ
継続的集計クエリを実行するときにリアルタイムクエリが無効になっている場合、クエリは完全に集計済みのデータに基づく結果のみを返します。 まだ集計されていない新しく受信した生データも表示するには、リアルタイムクエリを有効にします。
リアルタイムクエリを有効にします。
ALTER MATERIALIZED VIEW transaction_min_cagg SET (timescaledb.materialized_only = false);
リアルタイムクエリを無効にします。
ALTER MATERIALIZED VIEW transaction_min_cagg SET (timescaledb.materialized_only = true);
ネストされた集計
ネストされた集計は、継続的集計によって生成された マテリアライズドビューに基づいて継続的集計を作成します。 たとえば、時間集計結果に基づいて日次集計を作成したり、日次集計結果に基づいて月次集計を作成したりします。 これにより、データの冗長性が削減され、集計 パフォーマンスが向上します。
第 1 レベルの集計を作成します。 この例では、集計は 1 分間隔で実行されます。
CREATE MATERIALIZED VIEW transaction_min_cagg WITH (timescaledb.continuous) AS SELECT id, time_bucket(INTERVAL '1 min', tm) AS bucket, AVG(price) as avg, MAX(price) as max, MIN(price) as min FROM transaction_data GROUP BY id, bucket;
1 分集計の結果に基づいて 1 時間間隔でデータを集計するネストされた集計を作成します。
CREATE MATERIALIZED VIEW transaction_one_hour_mview WITH (timescaledb.continuous) AS SELECT id, time_bucket(INTERVAL '1 hour', bucket) AS bucket, AVG(avg) as avg, MAX(max) as max, MIN(min) as min FROM transaction_min_cagg GROUP BY id, time_bucket(INTERVAL '1 hour', bucket);
時系列圧縮
時系列パーティションが既存データであると判断された場合は、データ圧縮機能を有効にできます。 GanosBase TSDB は、テーブル全体と指定されたパーティションの圧縮機能を提供します。 圧縮により、データストレージスペースを節約できます。 圧縮率は 70% 以上で、ストレージコストを大幅に削減できます。
圧縮データは読み取りのみが可能で、書き込みはできません。
現在のバージョンでは、時系列圧縮機能はサポートされていません。 時系列圧縮機能を有効にするには、お問い合わせください。
拡張機能を削除する
DROP EXTENSION ganos_tsdb CASCADE;
DROP EXTENSION timescaledb CASCADE;