0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

時系列データの管理に関する覚書

Last updated at Posted at 2024-08-20

この記事で扱う内容

時系列データの管理に関して、以下の2点について扱います。この二つの観点は関連しています。

  • 分散環境における管理方法
  • データ保存期間

分散環境における時系列データの管理方法

分散データベースでは、データのパーティショニング(あるいはシャーディング)が行われます。
このパーティショニングは、(明示的にであれ、潜在的にであれ)何らかの値をもとに行われます。

Apache Cassandraでは、明示的に、パーティションの基準とする値に用いるキーを指定します。

時系列データを管理する場合のパーティションキー設計のパターンとして「タイムバケッティング(time bucketing)」があります。

CREATE TABLE device (
  deviceid INT,
  monthbucket TEXT,
  timestamp TIMESTAMP,
  ...
  PRIMARY KEY ((deviceid,monthbucket),timestamp));

ここでmonthbucketには、例えば202308のようにtimestamp値を構成する年と月のデータを格納することが考えられます(これは、あくまで例であり、後述のデータ保存期間との関係で、異なる粒度を選択することが考えられます)。

このような設計にすることにより、以下の2点の効果があります。

  • 検索性能
  • データ分散

検索性能

データ検索時に限られたパーティション(/ノード/物理サーバ)にアクセスすれば済むため、検索性能があがります。

データ分散

上述の検索性能を実現するだけであれば、timestampカラム自体をパーティションキーにすることが考えられます。しかし、少し考えればわかるように、これはパーティションキーの種類が、すぎに膨大になり、無限に増殖することを意味します。一般にこのようにタイムスタンプ値自体をパーティショニングの基準にすることはアンチパターンといえます。「タイムバケッティング(time bucketing)」の手法を用いることで、このアンチパターンを回避しつつ、時系列情報を検索に用いることができます。

実例

以下は、クエリの例です。monthbucketを検索に用いると同時にtimestampでより詳細な時間を指定します。そのために、timestampカラムは検索可能なカラム(Cassandraにおけるクラスタリングキー)として設定されている必要があります。

SELECT * FROM device
WHERE deviceid='123' AND monthbucket='202303'
AND timestamp >= '2023-03-01 00:00:00-0500'
AND timestamp < '2023-03-16 00:00:00-0500';

分散環境における時系列データの保存方法

問題

時系列データの管理においては、データが持続的に増え続けることへの考慮が必要です。
つまり、特に何の配慮も行わない場合、検索性能は、(どれだけ技術的な最適化が行われていたとしても)論理的に下がり続けることになります。

ここでは、時系列データを管理するためのひとつのパターンについて紹介します。

データ管理において、よくある考え方としては、古いデータを退避する、というものがあります。このことによって、そのテーブルのデータの量は一定量に保たれ、検索性能について、一貫した性能を期待することができます。

よくある手法では、テーブルから古くなったデータを抽出し、オブジェクトストアなどの他の環境に保存し、元のテーブルから削除するという方法があります。この場合、以下の2点について考慮する必要があります。

  • データの退避(移動)方法(ETLなどの活用)
  • (退避先からの)データの検索方法(データベースとは別の検索方法)

これらは、時系列データを管理するデータベースとは、他の技術によって実現することになります。

TTL利用

Apache Cassandraのように、データベースにはテーブルのデータに有効期限/TTL(time to live)を指定することによって、一定期間の後に、有効期限が過ぎたデータを削除する機能があります。

データの格納時に、TTLが設定されたテーブルと、TTLが設定されていないテーブルの二つにデータを格納することによって、上述の二つの問題を同時に解決することができます。

この二つのテーブルは、以下のようなイメージになります。

  • LATEST_DATA_WITH_TTL
  • HISTORICAL_DATA_WITHOUT_TTL

例えば、このテーブルへのクエリを行う要件の大部分(90%以上など)が、過去1か月のデータへのクエリである場合、TTLとして2か月程度(単純に現在時点から1か月前ではなく「先月のデータ」という要件も考慮すべき)を設定することが考えられます。このTTL期間設定は、クエリ要件と照らし合わせて、設計することになります。

この手法は、過去のデータをつねに(多少の検索性能は犠牲としても)アクティブな状態にしておきたいという要件を(オブジェクトストアへの別の検索手段を講じずに、たんに検索先テーブルを変更するだけで)満たすことができます。

また、このような手法と、従来の外部へのデータ退避とを組み合わせることも考えることができます。例えば、数か月前のデータをHISTORICAL_DATA_WITHOUT_TTLに移すことで、クエリの90%は、LATEST_DATA_WITH_TTLへのクエリとして予想された性能を確保します。その後、HISTORICAL_DATA_WITHOUT_TTLへのクエリ要件において、数年前のデータへのクエリ要件が例えば、1%以下であれば、その期間を超えるデータは、オブジェクトストアへ退避して、データベースの無制限のデータ容量を避けながら、1%以下のデータ検索の要件に対しては、マニュアル操作によるデータ復帰プロセスを含めて、例えばリクエストから一週間でデータ提供、といったサービスレベルを定めることが考えられます。

また、このことによりデータ退避処理期間中にテーブルへの検索性能が下がるといった問題についても、(検索要件の90%で)避けることができます。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?