第5章 データコラボレーション / 想定学習時間:30〜40分 / 最終確認:2026年8月

5-1. Time TravelとFail-safe(UNDROP・保持期間・ストレージ)

🎯 この節の学習目標

1. Time Travelとは:過去のデータに「時間旅行」する

Snowflake の Time Travel(タイムトラベル)は、更新や削除が行われる前の状態のデータに、定義された保持期間内であればいつでもアクセスできる機能です。誤った UPDATE や DELETE、さらにはテーブルの DROP までも、バックアップからの復元作業なしに取り消せます。これは、Snowflake がデータをイミュータブル(変更不可)なマイクロパーティションとして保存し、変更のたびに新しいパーティションを作成して古いものを保持期間中残しておく仕組みによって実現されています。

Time Travel でできることは大きく3つです。

できること使う構文典型的な場面
過去時点のデータをクエリするSELECT ... AT / BEFORE誤更新前の値の確認、変更前後の比較
過去時点の状態を復元するCREATE TABLE ... CLONE ... AT / BEFORE(5-2で詳述)誤更新前の状態でテーブルを作り直す
DROPしたオブジェクトを復活させるUNDROP TABLE / SCHEMA / DATABASE誤ってテーブルやデータベースごと削除してしまった

2. AT句とBEFORE句:3つの時点指定方法

過去のデータをクエリするには、FROM 句のテーブル名の後ろに AT または BEFORE を付けます。時点の指定方法は3種類あります。

指定方法意味
TIMESTAMP =>指定した時刻時点のデータ
OFFSET =>現在からさかのぼる秒数(負の値で指定。例:-3600 は1時間前)
STATEMENT =>指定したクエリIDの文が実行された時点

💡 具体例:Time Travelクエリ

-- 特定の時刻時点のデータを参照する
SELECT * FROM sales.public.orders
  AT(TIMESTAMP => '2026-08-01 09:00:00'::TIMESTAMP_LTZ);

-- 1時間前(3600秒前)のデータを参照する
SELECT * FROM sales.public.orders
  AT(OFFSET => -3600);

-- 指定したクエリIDの文が「実行された直後」の状態を参照する
SELECT * FROM sales.public.orders
  AT(STATEMENT => '01b2c3d4-0000-1234-0000-000000000001');

-- 指定したクエリIDの文が「実行される直前」の状態を参照する
SELECT * FROM sales.public.orders
  BEFORE(STATEMENT => '01b2c3d4-0000-1234-0000-000000000001');

AT は指定時点を含む状態BEFORE は指定した文(または時点)の直前の状態を返します。「誤った DELETE 文の直前に戻りたい」なら、その文のクエリIDを使った BEFORE(STATEMENT => ...) が最も確実です。

3. UNDROP:削除したオブジェクトの復活

DROP してしまったテーブル・スキーマ・データベースは、Time Travel の保持期間内であれば UNDROP コマンド1つで復活できます。データのコピーは発生せず、メタデータ操作だけで完了するため即時に戻ります。

DROP TABLE sales.public.orders;

-- 保持期間内なら1文で復活できる
UNDROP TABLE sales.public.orders;

-- スキーマ・データベースも同様に復活できる
UNDROP SCHEMA sales.public;
UNDROP DATABASE sales;

📝 試験のポイント

UNDROP できるのは Time Travel の保持期間内だけです。保持期間を過ぎて Fail-safe に移ったオブジェクトは、ユーザー自身では復元できません。また、同名のオブジェクトが既に存在する場合は UNDROP が失敗するため、先に既存オブジェクトをリネームしてから UNDROP します。復活対象は「DROP した時点の状態」であり、複数回 DROP した場合は最後に DROP したものから順に復活します。

4. DATA_RETENTION_TIME_IN_DAYS:保持期間の設定

Time Travel の保持期間は、パラメータ DATA_RETENTION_TIME_IN_DAYS で制御します。既定値は1日で、エディションとテーブル種別によって設定できる範囲が変わります。

対象StandardエディションEnterprise以上
permanent(永続)テーブル0〜1日(既定1日)0〜90日(既定1日)
transient / temporaryテーブル0〜1日(既定1日)0〜1日(既定1日。90日には延ばせない)

0に設定すると Time Travel は無効になり、DROP した瞬間に UNDROP もできなくなります。保持期間は ALTER 文で、アカウント・データベース・スキーマ・テーブルの各レベルに設定でき、下位レベルの設定が上位の設定を上書きします。

-- テーブル単位で保持期間を30日に延長する(Enterprise以上)
ALTER TABLE sales.public.orders SET DATA_RETENTION_TIME_IN_DAYS = 30;

-- スキーマ・データベース・アカウント単位でも設定できる
ALTER SCHEMA sales.public SET DATA_RETENTION_TIME_IN_DAYS = 7;
ALTER DATABASE sales     SET DATA_RETENTION_TIME_IN_DAYS = 7;
ALTER ACCOUNT            SET DATA_RETENTION_TIME_IN_DAYS = 0;  -- アカウント全体で無効化

5. Fail-safe:最後の砦

Fail-safe(フェイルセーフ)は、Time Travel の保持期間が終了した後に続く7日間の追加保護期間です。ただし Time Travel とは性格がまったく異なります。

Time TravelFail-safe
期間0〜90日(設定可能)7日固定(設定変更不可)
誰が使えるかユーザー自身(SQLでクエリ・クローン・UNDROP)Snowflakeサポートのみ(ユーザーはクエリ不可)
目的誤操作からのセルフサービス復旧、過去データの参照システム障害等に備えた災害復旧の最終手段
対象テーブルpermanent / transient / temporarypermanentテーブルのみ(transient / temporaryにはない)

Fail-safe のデータ復旧は Snowflake サポートへの依頼が必要で、復旧完了まで数時間から数日かかる可能性があります。「うっかり消したから Fail-safe から戻そう」という気軽な使い方はできない、文字どおり最後の砦だと理解してください。

現在のデータ通常のクエリ対象(アクティブなストレージ)
更新・削除・DROPから時間が経過
Time Travel 期間0〜90日(設定可能。0で無効化)/ ユーザーがAT・BEFORE・UNDROPで自由にアクセス
保持期間の終了
Fail-safe 期間7日固定 / Snowflakeサポートによる災害復旧のみ(permanentテーブルのみ)
7日経過
完全削除いかなる方法でも復元不可

図:データのライフサイクル。Time Travel はユーザーの領域、Fail-safe はSnowflakeサポートの領域

6. ストレージ課金への影響

Time Travel と Fail-safe のために保持される過去データも、ストレージ課金の対象です。課金されるのは変更・削除されたマイクロパーティションの分だけですが、注意すべきパターンがあります。

📝 試験のポイント

「Time Travel を90日に設定できるのはどのエディションか」→ Enterprise 以上、かつ permanent テーブルのみ。「Fail-safe の期間を変更できるか」→ できない(7日固定)。「Fail-safe のデータをユーザーがクエリできるか」→ できない(Snowflakeサポート経由のみ)。この3点は確実に押さえましょう。

✅ この節のまとめ

練習問題

問1. 誤って実行してしまったDELETE文のクエリIDが分かっている。そのDELETEが実行される「直前」の状態のテーブルをクエリする構文はどれか。

  1. SELECT * FROM t AT(STATEMENT => '<クエリID>');
  2. SELECT * FROM t BEFORE(STATEMENT => '<クエリID>');
  3. SELECT * FROM t AT(OFFSET => '<クエリID>');
  4. SELECT * FROM t BEFORE(TIMESTAMP => '<クエリID>');
解答と解説を見る

正解:B

BEFORE(STATEMENT => ...)は、指定したクエリIDの文が実行される直前の状態を返します。AのAT(STATEMENT => ...)はその文が実行された直後(変更を含む)の状態を返すため、DELETE後のデータになってしまいます。CのOFFSETに指定するのはクエリIDではなく現在からさかのぼる秒数(負の値)です。DのTIMESTAMPに指定するのは時刻であり、クエリIDではありません。

問2. DATA_RETENTION_TIME_IN_DAYSに関する説明として正しいものを2つ選べ。

  1. 既定値は1日であり、0に設定するとTime Travelは無効になる
  2. Standardエディションでもpermanentテーブルなら最大90日に設定できる
  3. Enterpriseエディション以上のpermanentテーブルは最大90日に設定できる
  4. transientテーブルはEnterpriseエディションなら最大90日に設定できる
解答と解説を見る

正解:AとC

既定値は1日で、0に設定するとTime Travelが無効になりUNDROPもできなくなります(A)。最大90日に延長できるのはEnterprise以上のエディションのpermanentテーブルだけです(C)。BはStandardエディションの上限が1日である点が誤りです。Dはtransient / temporaryテーブルの上限がエディションにかかわらず1日である点が誤りです。

問3. Fail-safeの説明として最も適切なものはどれか。

  1. Time Travel終了後の7日間で、ユーザーはAT句を使ってFail-safe内のデータをクエリできる
  2. Time Travel終了後の7日間で、データの復旧はSnowflakeサポートに依頼する必要があり、ユーザー自身はアクセスできない
  3. 保持期間はALTER ACCOUNTで最大90日まで延長できる
  4. permanent・transient・temporaryのすべてのテーブルタイプに適用される
解答と解説を見る

正解:B

Fail-safeはTime Travel終了後の7日間、システム障害等に備えてSnowflakeが保持する災害復旧専用の領域で、復旧にはSnowflakeサポートへの依頼が必要です。Aはユーザーがクエリできる点が誤りで、AT句が使えるのはTime Travel期間内だけです。CはFail-safeの期間が7日固定で変更不可のため誤りです。DはFail-safeがpermanentテーブルにしかない点が誤りで、transient / temporaryテーブルにFail-safeはありません。

問4. 毎晩全行を洗い替えする大容量のETLワークテーブルのストレージコストを抑えたい。最も適切な対策はどれか。

  1. permanentテーブルのままDATA_RETENTION_TIME_IN_DAYSを90日に設定する
  2. transientテーブルとして作成する
  3. Fail-safeの期間を0日に変更する
  4. 毎晩UNDROP TABLEを実行する
解答と解説を見る

正解:B

transientテーブルはFail-safeを持たず、Time Travelも最大1日のため、洗い替えのたびに積み上がる過去パーティションのストレージ課金を大幅に抑えられます。再作成可能なワークテーブルに適した定石です。Aは保持期間を最大化する設定であり、コストはむしろ増加します。CはFail-safeの期間がそもそも変更不可のため実行できません。DのUNDROPは削除の取り消しコマンドであり、ストレージコスト削減とは無関係です。