Amazon Timestreamの保存期間を短くしたとき、データが消えるか確認してみた

Amazon Timestreamの保存期間を短くしたとき、データが消えるか確認してみた

消えました……。保存期間の変更時はご注意ください。
Clock Icon2025.05.29

AWSには、マネージド型の時系列データベースとして、Amazon Timestreamがあります。PLCやセンサーなどの時系列データに向いています。

Amazon Timestreamは、データの保存期間を決めて利用します。

  • メモリストア: 1〜8766 時間(約1年)
  • マグネティックストア: 1〜73000日(約200年)

間違えてデータの保存期間を短くしちゃったとき、データがどうなるか気になったので、試してみました。

おすすめの方

  • Amazon Timestreamの保存期間を短くしたとき、データが消えるか知りたい方
  • Amazon Timestreamにboto3でデータを書き込みたい方

Amazon TimestreamをCloudFormationで作成する

まずは、3年分のデータを保存できるようにします。

テンプレートファイル

cfn.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon Timestream change retention Sample

Resources:
  TimestreamDatabase:
    Type: AWS::Timestream::Database
    Properties:
      DatabaseName: ChangeRetentionSampleDatabase

  TimestreamTable:
    Type: AWS::Timestream::Table
    Properties:
      DatabaseName: !Ref TimestreamDatabase
      TableName: change-retention-sample-table
      RetentionProperties:
        MemoryStoreRetentionPeriodInHours: 168  # 7 days
        MagneticStoreRetentionPeriodInDays: 1095  # 3 year
      MagneticStoreWriteProperties:
        EnableMagneticStoreWrites: true # マグネティックストアへの書き込みを有効にする

デプロイ

aws cloudformation deploy \
    --template-file cfn.yaml \
    --stack-name Amazon-Timestream-change-retention-Sample-Stack

Amazon Timestreamに3年分のデータを書き込む

3つのデバイスが1日1回、データを書き込んだ想定とします。

スクリプト

import boto3
import random
import json

from datetime import datetime, timedelta, timezone

from botocore.exceptions import ClientError

TIMESTREAM_DATABASE_NAME = "ChangeRetentionSampleDatabase"
TIMESTREAM_TABLE_NAME = "change-retention-sample-table"

client = boto3.client("timestream-write")

def main():
    JST = timezone(timedelta(hours=9), "JST")
    base_datatime = datetime(2025, 5, 26, 9, 0, 0, tzinfo=JST)
    base_unixtime = int(base_datatime.timestamp() * 1000)

    records = []

    # デバイス1〜3
    for device_number in range(1, 4):
        # 3年分のデータ(1日毎)
        for count in range(1 * 365 * 3):
            records.append(
                make_record(
                    base_unixtime - count * 24 * 3600 * 1000,  # 1日毎にする
                    f"device{device_number:04d}",
                    round(random.uniform(0, 40), 1),  # 温度の乱数
                    round(random.uniform(0, 100), 1),  # 湿度の乱数
                )
            )

    print(f"records: {len(records)}")

    # Timestreamに書き込む(書き込み制限が最大100件のため、分割している)
    for i in range(0, len(records), 100):
        write_records(
            TIMESTREAM_DATABASE_NAME,
            TIMESTREAM_TABLE_NAME,
            records[i : i + 100],
        )

def make_record(unixtime, device_id, temperature, humidity):
    return {
        "Dimensions": [
            {"Name": "deviceId", "Value": device_id, "DimensionValueType": "VARCHAR"},
        ],
        "MeasureValueType": "MULTI",  # マルチメジャーレコード
        "MeasureName": "sensorData",
        "Time": str(unixtime),
        "TimeUnit": "MILLISECONDS",
        "MeasureValues": [
            {
                "Name": "temperature",
                "Value": str(temperature),
                "Type": "DOUBLE",
            },
            {
                "Name": "humidity",
                "Value": str(humidity),
                "Type": "DOUBLE",
            },
        ],
    }

def write_records(database_name, table_name, records):
    try:
        resp = client.write_records(
            DatabaseName=database_name,
            TableName=table_name,
            Records=records,
        )
    except ClientError as e:
        if e.response["Error"]["Code"] == "RejectedRecordsException":
            print(e.response["Error"]["Message"])
            print(json.dumps(e.response["RejectedRecords"], indent=2))
        else:
            print(f"error: {e}")
        raise e

if __name__ == "__main__":
    main()

Amazon Timestreamで検索する(期間の変更前)

すべてのデータ件数を取得する

SELECT COUNT(*) AS total_records
FROM "ChangeRetentionSampleDatabase"."change-retention-sample-table"

期待通りです。

  • 3 x 365 x 3 = 3285

01_amazon_timestream

デバイスごとに最も古いデータを取得する

SELECT deviceId,
	MIN_BY(time, time) AS latest_timestamp,
	MIN_BY(temperature, time) AS latest_temperature,
	MIN_BY(humidity, time) AS latest_humidity
FROM "ChangeRetentionSampleDatabase"."change-retention-sample-table"
WHERE measure_name='sensorData'
GROUP BY deviceId
ORDER BY latest_timestamp DESC, deviceId ASC

約3年前のデータがありました。

02_amazon_timestream

Amazon Timestreamのデータ保持期間を短くする(3年->1年)

テンプレートファイル

マグネティックストアの期間を3年から1年に変更します。

cfn.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon Timestream change retention Sample

Resources:
  TimestreamDatabase:
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Type: AWS::Timestream::Database
    Properties:
      DatabaseName: ChangeRetentionSampleDatabase

  TimestreamTable:
    Type: AWS::Timestream::Table
    Properties:
      DatabaseName: !Ref TimestreamDatabase
      TableName: change-retention-sample-table
      RetentionProperties:
        MemoryStoreRetentionPeriodInHours: 168  # 7 days
        MagneticStoreRetentionPeriodInDays: 365  # 1 year
      MagneticStoreWriteProperties:
        EnableMagneticStoreWrites: true # マグネティックストアへの書き込みを有効にする

続けてデプロイします。

aws cloudformation deploy \
    --template-file cfn.yaml \
    --stack-name Amazon-Timestream-change-retention-Sample-Stack

Amazon Timestreamで検索する(期間の変更後)

すべてのデータ件数を取得する

SELECT COUNT(*) AS total_records
FROM "ChangeRetentionSampleDatabase"."change-retention-sample-table"

約1年分のデータ数になっていました。(メモリストアの7日分を考慮してます)

  • ( 1 x 365 x 3 ) + ( 7 x 3 ) = 1116

11_amazon_timestream

デバイスごとに最も古いデータを取得する

SELECT deviceId,
	MIN_BY(time, time) AS latest_timestamp,
	MIN_BY(temperature, time) AS latest_temperature,
	MIN_BY(humidity, time) AS latest_humidity
FROM "ChangeRetentionSampleDatabase"."change-retention-sample-table"
WHERE measure_name='sensorData'
GROUP BY deviceId
ORDER BY latest_timestamp DESC, deviceId ASC

こちらも、約1年前の日時のデータになっていました。

12_amazon_timestream

おまけ1: 慌てて1年から3年に戻してみたが、データは戻らなかった

保存期間を間違えて変更しちゃった(3年 -> 1年)と想定し、すぐさま「1年 -> 3年」に変更しました。そのあとデータを確認しましたが、1年分のままでした。失った2年分のデータは戻ってきませんでした。

おまけ2: UpdateReplacePolicyとDeletionPolicyは、効果なし

CloudFormationのテンプレートファイルで次の2つを指定しましたが、保存期間の変更阻止はできませんでした(リソース置換ではないため)。

  • UpdateReplacePolicy: Retain
  • DeletionPolicy: Retain
AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon Timestream change retention Sample

Resources:
  TimestreamDatabase:
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Type: AWS::Timestream::Database
    Properties:
      DatabaseName: ChangeRetentionSampleDatabase

  TimestreamTable:
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Type: AWS::Timestream::Table
    Properties:
      DatabaseName: !Ref TimestreamDatabase
      TableName: change-retention-sample-table
      RetentionProperties:
        MemoryStoreRetentionPeriodInHours: 168  # 7 days
        MagneticStoreRetentionPeriodInDays: 30
      MagneticStoreWriteProperties:
        EnableMagneticStoreWrites: true # マグネティックストアへの書き込みを有効にする

さいごに

保存期間を変更する場合は、慎重に実施しましょう。バックアップの存在も大切ですね。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.