Time Travelの理解と使用

Snowflake Time Travelでは、定義された期間内の任意の時点で履歴データ(変更または削除されたデータ)にアクセスできます。Time Travelは、次のタスクを実行するための強力なツールとして機能します。

  • 誤ってまたは意図的に削除された可能性のあるデータ関連オブジェクト(テーブル、スキーマ、およびデータベース)の復元。

  • 過去の重要なポイントからのデータの複製とバックアップ。

  • 指定された期間のデータ使用量/操作の分析。

このトピックの内容:

Time Travelの紹介

Time Travel in Continuous Data Protection lifecycle

Time Travelを使用すると、定義された期間内に次のアクションを実行できます。

  • 更新または削除された過去のデータのクエリ。

  • 過去の特定の時点またはその前に、テーブル、スキーマ、およびデータベース全体のクローンの作成。

  • 削除されたテーブル、スキーマ、およびデータベースを復元します。

定義された時間が経過すると、データは Snowflake Fail-safe に移動され、これらのアクションは実行できなくなります。

注釈

長時間実行されるTime Travelクエリは、クエリが完了するまで、アカウント内のデータとオブジェクト(テーブル、スキーマ、およびデータベース)をFail-safeに移動するのを遅らせます。

Time Travel SQL 拡張

Time Travelをサポートするために、次の SQL 拡張機能が実装されています。

  • SELECT ステートメントおよび CREATE ... CLONE コマンドで指定できる AT | BEFORE 句(オブジェクト名の直後)。この句では、次のパラメーターのいずれかを使用して、アクセスする正確な履歴データを特定します。

    • TIMESTAMP

    • OFFSET (現在時刻との秒単位の時差)

    • STATEMENT (ステートメントの識別子。例:クエリ ID)

  • テーブル、スキーマ、データベース用のUNDROP コマンド。

    Time Travel SQL extensions

データ保持期間

Snowflake Time Travelの重要な要素は、データ保持期間です。

データの削除またはデータを含むオブジェクトの削除など、テーブル内のデータが変更されると、Snowflakeは更新前のデータの状態を保持します。データ保持期間は、この履歴データが保持される日数を指定するため、Time Travel操作(SELECT、CREATE ... CLONE、UNDROP)をデータに対して実行できます。

標準の保持期間は1日(24時間)であり、すべてのSnowflakeアカウントで自動的に有効になります。

  • Snowflake Standard Editionの場合、アカウントおよびオブジェクトレベル(つまり、データベース、スキーマ、およびテーブル)で保持期間を0(またはデフォルトの1日に戻す)に設定できます。

  • Snowflake Enterprise Edition(またはそれ以上)の場合:

    • 一時データベース、スキーマ、およびテーブルの場合、保持期間を0(またはデフォルトの1日に戻す)に設定できます。同じことが仮テーブルにも当てはまります。

    • 永続データベース、スキーマ、およびテーブルの場合、保持期間は0から90日までの任意の値に設定できます。

注釈

オブジェクトの0日間の保持期間は、オブジェクトのTime Travelを事実上無効にします。

オブジェクトの保持期間が終了すると、履歴データは Snowflake Fail-safe に移動します。

  • 履歴データはクエリに使用できなくなりました。

  • 過去のオブジェクトはクローンできなくなりました。

  • 削除された過去のオブジェクトは復元できなくなりました。

Time Travelのデータ保持期間を指定するには:

  • ACCOUNTADMIN ロールを持つユーザーは、 DATA_RETENTION_TIME_IN_DAYS オブジェクトパラメーターを使用して、アカウントのデフォルトの保持期間を設定できます。

  • データベース、スキーマ、および個々のテーブルを作成するときに、同じパラメータを使用してデフォルトを明示的に上書きできます。

  • データベース、スキーマ、またはテーブルのデータ保持期間はいつでも変更できます。

Time Travelの有効化と無効化

Time Travelの有効化には、タスクは必要ありません。標準の1日の保持期間で自動的に有効になります。

Snowflake Enterprise Editionにアップグレードすると、データベース、スキーマ、およびテーブルに対して最大90日の長いデータ保持期間を構成できるようになります。拡張データ保持には追加のストレージが必要であり、これは毎月のストレージ料金に反映されます。ストレージ料金の詳細については、 Time TravelおよびFail-safeのストレージコスト をご参照ください。

アカウントのTime Travelを無効にすることはできません。ただし、オブジェクトの DATA_RETENTION_TIME_IN_DAYS に0の値を指定することで、個々のデータベース、スキーマ、およびテーブルに対して無効にすることはできます。

また、ACCOUNTADMIN ロールを持つユーザーは、アカウントレベルで DATA_RETENTION_TIME_IN_DAYS を0に設定できます。つまり、アカウントで作成されたすべてのデータベース(およびその後のすべてのスキーマとテーブル)にはデフォルトで保持期間がありません。ただし、このデフォルトは、任意のデータベース、スキーマ、またはテーブルに対していつでも上書きできます。

注意

いずれかのオブジェクトの DATA_RETENTION_TIME_IN_DAYS を0に設定する前に、特にオブジェクトが削除された場合の回復に関連するため、オブジェクトのTime Travelを無効にするかどうかを検討してください。つまり、保持期間のないオブジェクトが削除された場合、オブジェクトを復元できなくなります。

一般的なルールとして、特定のオブジェクトに対して(少なくとも)1日の値を維持することをお勧めします。

オブジェクトのデータ保持期間の指定

デフォルトでは、最大保持期間は1日(つまり、24時間)です。Snowflake Enterprise Edition(およびそれ以上)では、アカウントのデフォルトを最大90日までの任意の値に設定できます。

  • テーブル、スキーマ、またはデータベースを作成するときに、コマンドの DATA_RETENTION_TIME_IN_DAYS パラメーターを使用してアカウントのデフォルトを上書きできます。

  • データベースまたはスキーマに保持期間が指定されている場合、その期間はデフォルトでデータベース/スキーマに作成されたすべてのオブジェクトに継承されます。

オブジェクトのデータ保持期間の変更

テーブルのデータ保持期間を変更すると、新しい保持期間は、アクティブなすべてのデータと、現在Time Travelにあるすべてのデータに影響します。影響は、期間の増減に応じて異なります。

保持の延長

現在Time Travelにあるデータの保持期間が長くなります。

たとえば、10日間が保持期間のテーブルがあり、その期間を20日間に延長した場合、10日間の後に削除されるはずだったデータは、Fail-safeに移行する前にさらに10日間保持されるようになります。

これは、10日よりも古いデータや、既にFail-safeに移行しているデータには適用されないことに注意してください。

保持の短縮

Time Travelでデータが保持される時間を短縮します。

  • 保持期間が短縮された後に変更されたアクティブなデータには、新しく短縮された期間が適用されます。

  • 現在Time Travelにあるデータは、

    • データがまだ新しく短縮された期間内にある場合、Time Travelに残ります。

    • データが新しい期間外の場合は、Fail-safeに移行します。

たとえば、10日間の保持期間を持つテーブルがあり、その期間を1日間に短縮すると、2日目から10日目のデータはFail-safeに移行し、Time Travelからアクセスできるデータは1日目のみになります。

Time TravelからFail-safeにデータを移行するプロセスは、バックグラウンドプロセスによって実行されるため、変更はすぐには表示されません。Snowflakeは、データの移行を保証しますが、プロセスがいつ完了するかは指定しません。バックグラウンドプロセスが完了するまで、Time Travelを通じてデータにアクセスできます。

オブジェクトの保持期間を変更するには、適切な ALTER <オブジェクト> コマンドを使用します。たとえば、テーブルの保持期間を変更するには、

CREATE TABLE mytable(col1 NUMBER, col2 DATE) DATA_RETENTION_TIME_IN_DAYS=90;

ALTER TABLE mytable SET DATA_RETENTION_TIME_IN_DAYS=30;

注意

アカウントまたは個々のオブジェクトの保持期間を変更すると、保持期間が明示的に設定されていない下位レベルのオブジェクトの値すべてが変更されます。例:

  • アカウントレベルで保持期間を変更すると、明示的な保持期間を持たないすべてのデータベース、スキーマ、およびテーブルは、新しい保持期間を自動的に継承します。

  • スキーマレベルで保持期間を変更すると、明示的な保持期間を持たないスキーマ内のすべてのテーブルが新しい保持期間を継承します。

アカウントまたはアカウント内のオブジェクトの保持期間を変更するときは、変更により、予期または意図しないTime Travelの結果がもたらされる可能性があることに留意してください。特に、アカウントレベルで保持期間を0に変更することは お勧めしません

ドロップされたコンテナとオブジェクト保持の継承

現在、データベースが削除されると、子スキーマまたはテーブルのデータ保持期間は、データベースの保持とは明示的に異なるように設定されている場合、尊重されません。子スキーマまたはテーブルは、データベースと同じ期間保持されます。

同様に、スキーマが削除されると、子テーブルのデータ保持期間は、スキーマの保持とは異なるように明示的に設定されている場合、尊重されません。子テーブルは、スキーマと同じ期間保持されます。

これらの子オブジェクト(スキーマまたはテーブル)のデータ保持期間を尊重するには、データベースまたはスキーマを削除する に、明示的に削除します。

履歴データのクエリ

テーブルに対して DML 操作が実行されると、Snowflakeは定義された期間、テーブルデータの以前のバージョンを保持します。これにより、 AT | BEFORE 句を使用して以前のバージョンのデータをクエリできます。

この句は、保持期間内のテーブル履歴の指定されたポイント、またはその直前のデータのクエリをサポートします。指定されたポイントは、時間ベース(タイムスタンプまたは現在からの時間オフセットなど)にすることも、完了したステートメントの ID にすることもできます(例: SELECT または INSERT)。

例:

  • 次のクエリは、指定された タイムスタンプ で表される日時の時点で、テーブルから履歴データを選択します。

    SELECT * FROM my_table AT(TIMESTAMP => 'Mon, 01 May 2015 16:20:00 -0700'::timestamp_tz);
    
  • 次のクエリは、5分前の時点でテーブルから履歴データを選択します。

    SELECT * FROM my_table AT(OFFSET => -60*5);
    
  • 次のクエリは、指定されたステートメントによって行われた変更を含めないで、テーブルから履歴データを選択します。

    SELECT * FROM my_table BEFORE(STATEMENT => '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');
    

注釈

AT | BEFORE 句で指定された TIMESTAMP、 OFFSET、または STATEMENT がテーブルのデータ保持期間外にある場合、クエリは失敗し、エラーを返します。

履歴オブジェクトのクローニング

クエリに加えて、テーブル、スキーマ、またはデータベースの CREATE コマンドで CLONE キーワードと AT | BEFORE 句を使用して、オブジェクトの履歴の指定したポイントにオブジェクトの論理複製を作成できます。

例:

  • 次の  CREATE TABLE  コマンドは、指定されたタイムスタンプで表される日付と時刻のテーブルのクローンを作成します。

    CREATE TABLE restored_table CLONE my_table
      AT(TIMESTAMP => 'Mon, 09 May 2015 01:01:00 +0300'::timestamp_tz);
    
  • 次の  CREATE SCHEMA  コマンドは、現在時刻の1時間前に存在していたスキーマとそのすべてのオブジェクトのクローンを作成します。

    CREATE SCHEMA restored_schema CLONE my_schema AT(OFFSET => -3600);
    
  • 次の  CREATE DATABASE  コマンドは、指定されたステートメントの完了前に存在していたデータベースとそのすべてのオブジェクトのクローンを作成します。

    CREATE DATABASE restored_db CLONE my_db
      BEFORE(STATEMENT => '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');
    

オブジェクトのドロップと復元

オブジェクトのドロップ

テーブル、スキーマ、またはデータベースがドロップされても、すぐに上書きされたり、システムから削除されたりすることはありません。代わりに、オブジェクトのデータ保持期間の間保持され、その間はオブジェクトを復元できます。ドロップされたオブジェクトを Fail-safe に移動すると、復元できなくなります。

テーブル、スキーマ、またはデータベースをドロップするには、次のコマンドを使用します。

注釈

オブジェクトをドロップした後、同じ名前のオブジェクトを作成しても、オブジェクトは復元されません。代わりに、オブジェクトの新しいバージョンを作成します。元のドロップされたバージョンは引き続き使用可能であり、復元できます。

ドロップされたオブジェクトを復元すると、オブジェクトは元の場所に復元されます(つまり、新しいオブジェクトは作成されない)。

ドロップされたオブジェクトのリスト

ドロップされたテーブル、スキーマ、およびデータベースは、 HISTORY キーワードを指定した以下のコマンドを使用してリストできます。

例:

SHOW TABLES HISTORY LIKE 'load%' IN mytestdb.myschema;

SHOW SCHEMAS HISTORY IN mytestdb;

SHOW DATABASES HISTORY;

出力には、ドロップされたすべてのオブジェクトと、オブジェクトがドロップされた日時を表示する追加の DROPPED_ON 列が含まれます。オブジェクトが複数回ドロップされた場合、オブジェクトの各バージョンは出力に個別の行として含まれます。

注釈

オブジェクトの保持期間が過ぎ、オブジェクトが削除されると、 SHOW <オブジェクト型> HISTORY 出力に表示されなくなります。

オブジェクトの復元

システムからパージされていないドロップされたオブジェクト(つまり、オブジェクトは SHOW <オブジェクト型> HISTORY 出力に表示)は、次のコマンドを使用して復元できます。

UNDROP を呼び出すと、オブジェクトは DROP コマンドが実行される前の最新の状態に復元されます。

例:

UNDROP TABLE mytable;

UNDROP SCHEMA myschema;

UNDROP DATABASE mydatabase;

注釈

同じ名前のオブジェクトが既に存在する場合、 UNDROP は失敗します。既存のオブジェクトの名前を変更する必要があります。名前を変更すると、オブジェクトの以前のバージョンを復元できます。

アクセス制御の要件と名前の解決

オブジェクトをドロップするのと同様に、ユーザーがオブジェクトを復元するには OWNERSHIP 権限が必要です。さらに、ユーザーには、ドロップされたオブジェクトが復元されるデータベースまたはスキーマのオブジェクトタイプに対する CREATE 権限が必要です。

テーブルとスキーマの復元は、完全修飾オブジェクト名が指定されている場合でも、現在のスキーマまたは現在のデータベースでのみサポートされます。

例: テーブルの複数回のドロップおよび復元

次の例では、 mytestdb.public スキーマには2つのテーブル loaddata1proddata1 が含まれています。 loaddata1 テーブルがドロップされて2回再作成され、テーブルの3つのバージョンが作成されます。

  • 現在のバージョン

  • 2番目(つまり、最新)のドロップされたバージョン

  • 最初にドロップされたバージョン

次に、2つのドロップされたバージョンのテーブルを復元する方法の例を示します。

  1. 最初に、同じ名前の現在のテーブルの名前が loaddata3 に変更されます。これにより、タイムスタンプに基づいて、ドロップされたテーブルの最新バージョンを復元できます。

  2. 次に、最新のドロップされたバージョンのテーブルが復元されます。

  3. ドロップされたテーブルの最初のバージョンを復元できるように、復元されたテーブルの名前は loaddata2 に変更されます。

  4. 最後に、ドロップされたテーブルの最初のバージョンが復元されます。

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

DROP TABLE loaddata1;

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | Fri, 13 May 2016 19:04:46 -0700 |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

CREATE TABLE loaddata1 (c1 number);
INSERT INTO loaddata1 VALUES (1111), (2222), (3333), (4444);

DROP TABLE loaddata1;

CREATE TABLE loaddata1 (c1 varchar);

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Fri, 13 May 2016 19:06:01 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 0    | 0     | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:05:32 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 4    | 4096  | PUBLIC | 1              | Fri, 13 May 2016 19:05:51 -0700 |
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | Fri, 13 May 2016 19:04:46 -0700 |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

ALTER TABLE loaddata1 RENAME TO loaddata3;

UNDROP TABLE loaddata1;

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Fri, 13 May 2016 19:05:32 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 4    | 4096  | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:06:01 -0700 | LOADDATA3 | MYTESTDB      | PUBLIC      | TABLE |         |            | 0    | 0     | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | Fri, 13 May 2016 19:04:46 -0700 |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

ALTER TABLE loaddata1 RENAME TO loaddata2;

UNDROP TABLE loaddata1;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:05:32 -0700 | LOADDATA2 | MYTESTDB      | PUBLIC      | TABLE |         |            | 4    | 4096  | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:06:01 -0700 | LOADDATA3 | MYTESTDB      | PUBLIC      | TABLE |         |            | 0    | 0     | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+