このページでは、Spanner テーブルの有効期間(TTL)の使用方法について説明します。詳しくは、TTL についてをご覧ください。
準備
開始する前に、以下のベスト プラクティスに従ってください。
バックアップとポイントインタイム リカバリを有効にする
TTL をテーブルに追加する前に、Spanner のバックアップと復元を有効にすることをお勧めします。これにより、TTL ポリシーで誤ってデータを削除した場合に、データベースを完全に復元できます。
ポイントインタイム リカバリを有効にしている場合は、削除されたデータが構成されたバージョンの保持期間内にあれば、バックアップから完全に復元することなく、それを表示して復元できます。過去のデータの読み取りについては、ステイル読み取りを実行するをご覧ください。
古いデータをクリーンアップする
TTL を使用するのが初めてで、最初の実行で多数の行を削除する場合は、まずパーティション分割 DMLを手動で使用する古いデータのクリーンアップを検討します。これにより、リソースの使用状況を TTL バックグラウンド プロセスにまかせるのではなく、より細かく制御できます。TTL は低い優先度で実行され、増分クリーンアップに最適です。ただし、Spanner の内部作業スケジューラはユーザークエリなどの他の作業を優先するため、ビジー状態のデータベースで最初の行セットを削除するための時間が長くなる可能性があります。
条件を確認する
Google SQL テーブルでは、TTL を有効にする前に行削除ポリシーが影響を受けるデータを確認する場合、同じ条件を使用してテーブルに対してクエリを実行できます。次に例を示します。
GoogleSQL
SELECT COUNT(*)
FROM CalculatedRoutes
WHERE TIMESTAMP_ADD(CreatedAt, INTERVAL 30 DAY) < CURRENT_TIMESTAMP();
必要な権限
データベースのスキーマを変更するには、spanner.databases.updateDdl 権限を有する必要があります。詳細については、Spanner のアクセス制御をご覧ください。
行削除ポリシーを作成する
GoogleSQL
GoogleSQL を使用して行削除ポリシーを作成するには、新しいテーブルの作成時に ROW DELETION POLICY
句を定義するか、ポリシーを既存のテーブルに追加します。この句には列と間隔の式が含まれます。
テーブルの作成時にポリシーを追加するには:
CREATE TABLE MyTable( Key INT64, CreatedAt TIMESTAMP, ) PRIMARY KEY (Key), ROW DELETION POLICY (OLDER_THAN(timestamp_column, INTERVAL num_days DAY));
ここで
timestamp_column
は、型がTIMESTAMP
の既存の列である必要があります。commit タイムスタンプのある列は、生成された列のように、有効です。ただし、commit タイムスタンプ列を参照する生成された列は指定できません。num_days
は、行が削除対象としてマークされているtimestamp_column
のタイムスタンプから経過した日数です。この値は、マイナスでない整数にする必要があります。単位はDAY
のみサポートされています。
既存のテーブルにポリシーを追加するには、ALTER TABLE
ステートメントを使用します。1 つのテーブルには、行の削除ポリシーを最大 1 つ含めることができます。ポリシーが存在するテーブルに行削除ポリシーを追加すると、エラーが発生します。さらに指定高度な行削除ロジックを指定するには、生成された列の TTLをご覧ください。
ALTER TABLE Albums ADD ROW DELETION POLICY (OLDER_THAN(timestamp_column, INTERVAL num_days DAY));
PostgreSQL
PostgreSQL を使用して行削除ポリシーを作成するには、新しいテーブルの作成時に TTL INTERVAL
句を定義するか、ポリシーを既存のテーブルに追加します。
テーブルの作成時にポリシーを追加するには:
CREATE TABLE mytable ( key bigint NOT NULL, timestamp_column_name TIMESTAMPTZ, PRIMARY KEY(key) ) TTL INTERVAL interval_spec ON timestamp_column_name;
ここで
timestamp_column_name
はデータ型TIMESTAMPTZ
を含む列である必要があります。この列は、CREATE TABLE
ステートメントで作成する必要があります。commit タイムスタンプのある列は、生成された列のように、有効です。ただし、commit タイムスタンプ列を参照する生成された列は指定できません。interval_spec
は、行が削除対象としてマークされているtimestamp_column_name
のタイムスタンプから経過した日数です。この値は、日数を表す負でない整数にする必要があります。たとえば、'3 days'
は許されますが、'3 days - 2 minutes'
はエラーを返します。
既存のテーブルにポリシーを追加するには、ALTER TABLE
ステートメントを使用します。1 つのテーブルには、TTL ポリシーを最大 1 つ設定できます。ポリシーがすでに存在するテーブルに TTL ポリシーを追加すると、エラーが発生します。さらに高度な TTL ロジックを指定するには、生成された列の TTLをご覧ください。
既存のテーブルにポリシーを追加するには:
ALTER TABLE albums
ADD COLUMN timestampcolumn TIMESTAMPTZ;
ALTER TABLE albums
ADD TTL INTERVAL '5 days' ON timestampcolumn;
制限事項
行削除ポリシーには次の制限があります。
外部キーで参照されるテーブルの TTL
以下には行削除ポリシーを作成することはできません。
- ON DELETE CASCADE 制約を含まない外部キーで参照されるテーブル。
- ON DELETE CASCADE 参照アクションを含まない外部キーによって参照されるテーブルの親。
次の例では、Customers
テーブルに行削除ポリシーを追加できません。これは、Orders
テーブルの外部キーによって行削除ポリシーが参照されていて、ON DELETE CASCADE 制約がないためです。顧客を削除すると、この外部キー制約に違反する可能性があります。また、Districts
テーブルに行削除ポリシーを追加することもできません。Districts
から行を削除すると、子 Customers
テーブルで削除がカスケードされ、Orders
テーブルの外部キー制約に違反する可能性があります。
GoogleSQL
CREATE TABLE Districts (
DistrictID INT64
) PRIMARY KEY (DistrictID);
CREATE TABLE Customers (
DistrictID INT64,
CustomerID INT64,
CreatedAt TIMESTAMP
) PRIMARY KEY (DistrictID, CustomerID),
INTERLEAVE IN PARENT Districts ON DELETE CASCADE;
CREATE TABLE Orders (
OrderID INT64,
DistrictID INT64,
CustomerID INT64,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (DistrictID, CustomerID) REFERENCES Customers (DistrictID, CustomerID)
) PRIMARY KEY (OrderID);
PostgreSQL
CREATE TABLE districts (
districtid bigint NOT NULL,
PRIMARY KEY(districtid)
);
CREATE TABLE customers (
districtid bigint NOT NULL,
customerid bigint NOT NULL,
createdat timestamptz,
PRIMARY KEY(districtid, customerid)
) INTERLEAVE IN PARENT districts ON DELETE CASCADE;
CREATE TABLE orders (
orderid bigint NOT NULL,
districtid bigint,
customerid bigint,
PRIMARY KEY(orderid),
CONSTRAINT fk_customerorder FOREIGN KEY (districtid, customerid) REFERENCES customers (districtid, customerid)
);
ON DELETE CASCADE
を使用する外部キー制約によって参照されるテーブルに行削除ポリシーを作成できます。次の例では、Customers
テーブルに行削除ポリシーを作成できます。これは、Orders
テーブルで定義された外部キー制約 CustomerOrder
によって参照されます。TTL が Customers
の行を削除すると、削除は Orders
テーブル内の一致する行にカスケードされます。
GoogleSQL
CREATE TABLE Districts (
DistrictID INT64,
CreatedAt TIMESTAMP
) PRIMARY KEY (DistrictID),
ROW DELETION POLICY (OLDER_THAN(CreatedAt, INTERVAL 1 DAY));
CREATE TABLE Customers (
DistrictID INT64,
CustomerID INT64,
CreatedAt TIMESTAMP
) PRIMARY KEY (DistrictID, CustomerID),
INTERLEAVE IN PARENT Districts ON DELETE CASCADE,
ROW DELETION POLICY (OLDER_THAN(CreatedAt, INTERVAL 1 DAY));
CREATE TABLE Orders (
OrderID INT64,
DistrictID INT64,
CustomerID INT64,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (DistrictID, CustomerID) REFERENCES Customers (DistrictID, CustomerID) ON DELETE CASCADE
) PRIMARY KEY (OrderID);
PostgreSQL
CREATE TABLE districts (
districtid bigint NOT NULL,
createdat timestamptz,
PRIMARY KEY(districtid)
) TTL INTERVAL '1 day' ON createdat;
CREATE TABLE customers (
districtid bigint NOT NULL,
customerid bigint NOT NULL,
createdat timestamptz,
PRIMARY KEY(districtid, customerid)
) INTERLEAVE IN PARENT districts ON DELETE CASCADE
TTL INTERVAL '1 day' ON createdat;
CREATE TABLE orders (
orderid bigint NOT NULL,
districtid bigint,
customerid bigint,
PRIMARY KEY(orderid),
CONSTRAINT fk_customerorder FOREIGN KEY (districtid, customerid) REFERENCES customers (districtid, customerid) ON DELETE CASCADE
);
同様に、ON DELETE CASCADE
外部キー制約によって参照されるテーブルの親に行削除ポリシーを作成できます。
デフォルト値が含まれる列に対する TTL
行削除ポリシーでは、デフォルト値があるタイムスタンプ列を使用できます。通常、デフォルト値は CURRENT_TIMESTAMP
です。列に明示的に値が割り当てられていない場合や、INSERT
または UPDATE
ステートメントによって列がデフォルト値に設定されている場合は、デフォルト値がルール計算で使用されます。
次の例で、テーブル Customers
にある列 CreatedAt
のデフォルト値は、行が作成されたタイムスタンプです。
GoogleSQL
CREATE TABLE Customers (
CustomerID INT64,
CreatedAt TIMESTAMP DEFAULT (CURRENT_TIMESTAMP())
) PRIMARY KEY (CustomerID);
詳細については、GoogleSQL データ定義言語のDEFAULT(式)をご覧ください。
PostgreSQL
CREATE TABLE customers (
customerid bigint NOT NULL,
createdat timestamptz DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(customerid)
);
詳細については、「PostgreSQL のデータ定義言語」のCREATE TABLE をご覧ください。
生成された列の TTL
行削除ポリシーでは、生成された列を使用して、より高度なルールを表現できます。たとえば、複数の列の greatest
タイムスタンプ(GoogleSQL または PostgreSQL)に行削除ポリシーを定義することや、別の値をタイムスタンプにマッピングすることができます。
GoogleSQL
次のテーブル Orders
は、販売注文を追跡します。テーブル所有者は、キャンセルされた注文を 30 日後、キャンセルされていない注文を 180 日後に削除する行削除ポリシーを設定したいと考えています。
Spanner TTL では、テーブルあたり 1 つの行削除ポリシーのみが許可されます。2 つの条件を 1 つの列に表現するには、IF
ステートメントを含む生成列を使用します。
CREATE TABLE Orders (
OrderId INT64 NOT NULL,
OrderStatus STRING(30) NOT NULL,
LastModifiedDate TIMESTAMP NOT NULL,
ExpiredDate TIMESTAMP AS (IF(OrderStatus = 'Cancelled',
TIMESTAMP_ADD(LastModifiedDate, INTERVAL 30 DAY),
TIMESTAMP_ADD(LastModifiedDate, INTERVAL 180 DAY))) STORED,
) PRIMARY KEY(OrderId),
ROW DELETION POLICY (OLDER_THAN(ExpiredDate, INTERVAL 0 DAY));
ステートメントは、ExpiredDate
という名前の列を作成し、注文ステータスに応じて 30 日または 180 日を LastModifiedDate
に加算します。次に、INTERVAL 0 day
を指定し、ExpiredDate
列に保存された日付の行を期限切れにするように、行削除ポリシーを定義します。
PostgreSQL
次のテーブル Orders
は、販売注文を追跡します。テーブル オーナーは、30 日間の非アクティブ期間があった行を削除する行削除ポリシーを設定したいと考えています。
Spanner TTL では、テーブルあたり 1 つの行削除ポリシーのみが許可されます。2 つの条件を 1 つの列に表現するには、生成列を作成します。
CREATE TABLE orders (
orderid bigint NOT NULL,
orderstatus varchar(30) NOT NULL,
createdate timestamptz NOT NULL,
lastmodifieddate timestamptz,
expireddate timestamptz GENERATED ALWAYS AS (GREATEST(createdate, lastmodifieddate)) STORED,
PRIMARY KEY(orderid)
) TTL INTERVAL '30 days' ON expireddate;
このステートメントは、2 つの日付(LastModifiedDate
または CreateDate
)の新しい方を求める ExpiredDate
という名前の生成列を作成します。次に、注文後 30 日で行を期限切れにするか、その 30 日以内に注文が変更された場合は削除の期限がさらに 30 日延長される行削除ポリシーを定義します。
TTL とインターリーブされたテーブル
インターリーブされたテーブルは、1 対多の子テーブルにある関連する行を親テーブルの行に関連付けるパフォーマンス最適化です。親テーブルに行削除ポリシーを追加するには、インターリーブされた子テーブルで ON DELETE CASCADE
を指定する必要があります。つまり、子行は親行とともにアトミックに削除されます。これにより、親テーブルに対する削除でも同じトランザクション内の関連する子行が削除されるように、参照整合性が確保されます。Spanner TTL は、ON DELETE NO ACTION
をサポートしません。
トランザクションの最大サイズ
Spanner には、トランザクション サイズの上限があります。インデックス付きの列がある大規模な親子階層での削除のカスケードは、こうした上限を超え、1 つ以上の TTL オペレーションが失敗する可能性があります。オペレーションが失敗した場合、TTL は 1 つの親行まで縮小したバッチで再試行します。ただし、単一の親行でも、大きな子階層がミューテーションの上限を超える場合があります。
失敗したオペレーションは TTL 指標で報告されます。
1 つの行とそのインターリーブされた子が大きすぎて削除できない場合は、親テーブルのポリシーの他に、子テーブルにも行削除ポリシーを直接接続できます。子テーブルのポリシーは、親行より前に子行が削除されるように構成する必要があります。
次の 2 つのステートメントが適用される場合は、子テーブルに行削除ポリシーを付加することを検討してください。
- 子テーブルにはそれに関連付けられている任意のグローバル インデックスがあります。
- 親の行ごとに多数の(100 を超える)子の行が想定されます。
行削除ポリシーを削除する
既存の行削除ポリシーはテーブルから削除できます。テーブルに行削除ポリシーがない場合は、エラーが返されます。
GoogleSQL
ALTER TABLE MyTable
DROP ROW DELETION POLICY;
PostgreSQL
ALTER TABLE mytable
DROP TTL;
行削除ポリシーを削除すると、バックグラウンドで実行されている TTL プロセスが直ちに中止されます。進行中のプロセスですでに削除された行は、削除されたままになります。
行削除ポリシーによって参照されている列を削除する
Spanner では、行削除ポリシーによって参照されている列を削除できません。最初に、行削除ポリシーを削除してから、列を削除します。
テーブルの行削除ポリシーを表示する
Spanner テーブルの行削除ポリシーを表示できます。
GoogleSQL
SELECT TABLE_NAME, ROW_DELETION_POLICY_EXPRESSION
FROM INFORMATION_SCHEMA.TABLES
WHERE ROW_DELETION_POLICY_EXPRESSION IS NOT NULL;
詳細については、GoogleSQL 言語データベースの情報スキーマをご覧ください。
PostgreSQL
SELECT table_name, row_deletion_policy_expression
FROM information_schema.tables
WHERE row_deletion_policy_expression is not null;
詳細については、PostgreSQL 言語データベースの情報スキーマをご覧ください。
行削除ポリシーを変更する
既存の行削除ポリシーの列または間隔式は変更できます。次の例では、列を CreatedAt
から ModifiedAt
に切り替えて、間隔を 1 DAY
から 7 DAY
に拡張します。テーブルに行削除ポリシーがない場合は、エラーが返されます。
GoogleSQL
ALTER TABLE MyTable
REPLACE ROW DELETION POLICY (OLDER_THAN(ModifiedAt, INTERVAL 7 DAY));
PostgreSQL
ALTER TABLE mytable
ALTER TTL INTERVAL '7 days' ON timestampcolumn;