Amazon Timestreamの保存期間を短くしたとき、データが消えるか確認してみた
AWSには、マネージド型の時系列データベースとして、Amazon Timestreamがあります。PLCやセンサーなどの時系列データに向いています。
Amazon Timestreamは、データの保存期間を決めて利用します。
- メモリストア: 1〜8766 時間(約1年)
- マグネティックストア: 1〜73000日(約200年)
間違えてデータの保存期間を短くしちゃったとき、データがどうなるか気になったので、試してみました。
おすすめの方
- Amazon Timestreamの保存期間を短くしたとき、データが消えるか知りたい方
- Amazon Timestreamにboto3でデータを書き込みたい方
Amazon TimestreamをCloudFormationで作成する
まずは、3年分のデータを保存できるようにします。
テンプレートファイル
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
デバイスごとに最も古いデータを取得する
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年前のデータがありました。
Amazon Timestreamのデータ保持期間を短くする(3年->1年)
テンプレートファイル
マグネティックストアの期間を3年から1年に変更します。
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
デバイスごとに最も古いデータを取得する
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年前の日時のデータになっていました。
おまけ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 # マグネティックストアへの書き込みを有効にする
さいごに
保存期間を変更する場合は、慎重に実施しましょう。バックアップの存在も大切ですね。