## What — タイムトラベル BigQueryはテーブルの変更履歴を一定期間そのまま保持している。この仕組みがタイムトラベルで、クエリに `FOR SYSTEM_TIME AS OF <時刻>` を付けると「その時刻のテーブル」を読める。バックアップを取っていなくても、直近の事故なら自力で戻せるということ。 > [!warning] > 保持期間はデフォルトで7日間(データセット単位で2〜7日に変更可)。その範囲を過ぎた時点の状態はもう読めないので、気づいたらすぐ動く。なお、テーブルごと消してしまった場合はこの書き方では戻せず、`UNDROP TABLE` を使う。 戻し方の選択肢は3つ。 - 安全に別テーブルへ退避する - 既存テーブルを丸ごと置き換える - 消えた行だけ差し戻す ## How — データを復元する方法 **方法1: 新しいテーブルに復元(推奨)** 過去のデータを新しいテーブルにコピーします。現在のテーブルには一切触らないので、復元結果を見比べてから本番を差し替えられる。 ```sql CREATE TABLE `PROJECT_ID.DATASET.TABLE_RESTORED` AS SELECT * FROM `PROJECT_ID.DATASET.TABLE` FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR); ``` **方法2: 既存のテーブルを上書きして復元** 既存のテーブルを過去のデータで置き換えます(注意: 現在のデータは失われます)。参照しているクエリやビューを直さずに済む反面、指定時刻を間違えると二次被害になる。 ```sql CREATE OR REPLACE TABLE `PROJECT_ID.DATASET.TABLE` AS SELECT * FROM `PROJECT_ID.DATASET.TABLE` FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR); ``` **方法3: 特定の行だけ復元** 削除された行だけを復元する場合。事故のあとも新しい行が入り続けているテーブルは、丸ごと戻すと最新分まで巻き戻ってしまうので、この差分方式になる。 ```sql -- 削除された行を確認 SELECT * FROM `PROJECT_ID.DATASET.TABLE` FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR) WHERE id NOT IN ( SELECT id FROM `PROJECT_ID.DATASET.TABLE` ); -- 削除された行を挿入 INSERT INTO `PROJECT_ID.DATASET.TABLE` SELECT * FROM `PROJECT_ID.DATASET.TABLE` FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR) WHERE id NOT IN ( SELECT id FROM `PROJECT_ID.DATASET.TABLE` ); ``` まず SELECT で「何が戻るのか」を目視してから INSERT する順番が大事。いきなり書き込むと、重複行を作って壊し直すことになる。 ## 関連 - [[Google Cloud]] - [[データ基盤]] - [[BigQuery]] - [[Cloud StorageとBigQuery]]