クローニングに関する考慮事項

このトピックでは、Snowflakeのオブジェクト、特にデータベース、スキーマ、および非仮テーブルをクローンする際の重要な考慮事項について説明します。 DDL および DML トランザクション(ソースオブジェクト上)、Time Travel、データ保持期間などの要因は、オブジェクトのクローンに影響を与える可能性があります。

このトピックの内容:

クローンオブジェクトのアクセス制御権限

クローンオブジェクトは、ソースオブジェクト自体に付与された権限を保持しません(つまり、クローンはソースと同じ権限を自動的に持ちません)。システム管理者またはクローンされたオブジェクトの所有者は、新しく作成されたクローンに必要な権限を明示的に付与する必要があります。

ただし、ソースオブジェクトがソースに含まれる子オブジェクトのデータベースまたはスキーマである場合、クローンは対応する子オブジェクトに対して付与されたすべての権限を複製します。

  • データベースの場合、含まれるオブジェクトには、スキーマ、テーブル、ビューなどがあります。

  • スキーマの場合、含まれるオブジェクトには、テーブル、ビューなどがあります。

クローニングとSnowflakeオブジェクト

このセクションでは、特定のSnowflakeオブジェクトに関する特別なクローニングの考慮事項について説明します。

クローニングとステージ

次のルールは、ステージ、またはステージを含むオブジェクト(つまり、データベースとスキーマ)のクローニングに適用されます。

  • 個々の外部の名前付きステージをクローンできます。内部の名前付きステージはクローンできません。

  • データベースまたはスキーマをクローンする場合、

    • クローニング操作の開始時にソースに存在していた外部の名前付きステージがクローンされます。

    • テーブルはクローンされます。つまり、内部ステージもクローンされます。

    • 内部の名前付きステージは、クローンされ ません

ステージのクローン方法に関係なく、クローンはソースからのファイルを 含みません。つまり、クローンされたステージはすべて空です。

クローニングとパイプ

データベースまたはスキーマがクローンされる場合、内部(つまり、Snowflake)ステージを参照するソースコンテナーに含まれるパイプは、クローン されません

ただし、外部ステージを参照するパイプはクローンされます。これにより、次の動作が発生します。

  • ターゲットテーブルがパイプ定義の COPY ステートメントで完全修飾されている場合( データベース名.スキーマ名.テーブル名 または スキーマ名.テーブル名 の形式)、これにより、各パイプによってソースデータベースまたはスキーマのターゲットテーブルに重複データがロードされる可能性があります。

  • ターゲットテーブルがパイプ定義で完全 修飾されていない 場合、データはソースおよびクローンされたデータベース/スキーマのターゲットテーブル(例: mytable)にロードされます。

クローニングとストリーム

現在、ソーステーブルとストリームを含むデータベースまたはスキーマのクローンが作成されると、(クローン内の)ストリーム内の未使用のレコードにアクセスできなくなります。この動作は、テーブルの Time Travel と一致しています。テーブルのクローンが作成される場合、テーブルクローンの履歴データは、クローンが作成された時間/時点で開始されます。

クローニングとタスク

タスクを含むデータベースまたはスキーマがクローンされると、クローン内のタスクはデフォルトで一時停止されます。タスクは個別に再開できます( ALTER TASK ... RESUME を使用)。

クローニングに対する DDL の影響

クローニングは高速ですが、瞬時ではありません。特に大きなオブジェクト(例:テーブル)の場合はそうです。そのため、クローニング操作の進行中にソースオブジェクトで DDL ステートメントが実行される場合(例:スキーマ内のテーブル名の変更)、変更がクローンに反映されない可能性があります。これは、 DDL ステートメントがアトミックであり、複数ステートメントトランザクションの一部ではないためです。

さらに、Snowflakeは、クローン作成操作の開始時にどのオブジェクト名が存在し、どの名前が変更されたかを記録しません。そのため、ソースの子オブジェクトの名前を変更(またはドロップして再作成)する DDL ステートメントは、進行中のクローニング操作と競合し、名前の競合を引き起こす可能性があります。

次の例では、 t_sales テーブルがドロップされ、また別のテーブルが変更され、親データベースのクローン作成中にドロップされたテーブルと同じ名前が付けられているため、エラーが発生します。

CREATE OR REPLACE DATABASE staging_sales CLONE sales;

DROP TABLE sales.public.t_sales;

ALTER TABLE sales.public.t_sales_20170522 RENAME TO sales.public.t_sales;

002002 (42710): None: SQL compilation error: Object 'T_SALES' already exists.

ちなみに

クローニング操作中の名前解決の競合を避けるために、クローニング操作が完了するまでは、オブジェクトの名前をドロップされたオブジェクトが以前使用していた名前に変更しないことをお勧めします。

クローニングに対する DML およびデータ保持の影響

DATA_RETENTION_TIME_IN_DAYS パラメーターは、オブジェクトでTime Travelアクションを実行するためにSnowflakeが履歴データを保持する日数を指定します。Time Travelで保持されるデータにはテーブルレベルでストレージコストが発生するため、一部のユーザーは一部のテーブルでこのパラメーターを 0 に設定し、これらのテーブルのデータ保持を事実上無効にします(つまり、値が 0 に設定されている場合、Time Travel DML トランザクションで保持されているデータは消去され、追加のストレージコストはごくわずかです)。

特に大きなテーブルの場合、クローニング操作には時間がかかります。この期間中、 DML トランザクションはソーステーブルのデータを変更できます。その後、Snowflakeは、操作の開始時に存在していたテーブルデータをクローンしようとします。ただし、クローニング中に発生する DML トランザクションのデータがパージされると(テーブルの保持時間が 0 であるため)、操作を完了するためのデータがないため、次のようなエラーが生成されます。

ProgrammingError occured: "000707 (02000): None: Data is not available." with query id None

ちなみに

回避策として、オブジェクトをクローニングする際に、次のベストプラクティスの どちらか をお勧めします。

  • 可能であれば、クローニング操作が完了するまで、ソースオブジェクト(またはその子)で DML トランザクションを実行しないでください。

  • これが不可能な場合は、クローニングを開始する前に、スキーマ(またはデータベース全体をクローンする場合はデータベース)のすべてのテーブルに DATA_RETENTION_TIME_IN_DAYS=1 を設定します。操作が完了したら、必要に応じて、ソース内にあるこれらのテーブルのパラメーター値を 0 にリセットしてください。

    クローンテーブルの値を 0 に設定することもできます(クローンテーブルに DML の変更を加える予定で、テーブルのTime Travelに追加のストレージコストをかけたくない場合)。

Time Travelを使用したクローニング(データベース、スキーマ、およびテーブルのみ)

このセクションでは、 Time Travel を使用して、過去の特定の時間/ポイントでオブジェクトをクローンする際の考慮事項について説明します。

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

ソースオブジェクトが AT | BEFORE 句で指定された時間/ポイントに存在しなかった場合は、エラーが返されます。

次の例では、 CREATE TABLE ... CLONE ステートメントは、ソーステーブルが存在しなかった過去(30分前)の時点でクローンしようとします。

CREATE TABLE t_sales (numeric integer) data_retention_time_in_days=1;

CREATE OR REPLACE TABLE sales.public.t_sales_20170522 CLONE sales.public.t_sales at(offset => -60*30);

002003 (02000): SQL compilation error:
Object 'SALES.PUBLIC.T_SALES' does not exist.

また、指定した時間/ポイントに存在しなかった子オブジェクトはクローンされません。

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

クローンオブジェクトは、ステートメントの実行時にソースオブジェクトの定義を継承します。定義には、オブジェクト名、コメント、テーブル列などが含まれます。

次の例では、テーブル t_sales の名前が t_sales_20170522 に変更され、名前が変更されたテーブルにデータが挿入されます。テーブルを含むスキーマは、テーブルの名前が変更されてデータが挿入される30分前にクローンされます。クローンには、以前の名前ではなく現在の名前のテーブルが含まれますが、指定された時間のデータのスナップショットが含まれます。

CREATE OR REPLACE TABLE t_sales (numeric integer) data_retention_time_in_days=1;

INSERT INTO  t_sales (numeric)
VALUES (1),(2),(3);

ALTER TABLE sales.public.t_sales RENAME TO sales.public.t_sales_20170522;

INSERT INTO  t_sales_20170522 (numeric)
VALUES (4);

CREATE OR REPLACE SCHEMA sales.private CLONE sales.public at(offset => -60*30);

USE SCHEMA sales.private;

SHOW TABLES;

+-------------------------------+------------------+---------------+-------------+-------+---------+------------+------+-------+----------+----------------+
| created_on                    | name             | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner    | retention_time |
|-------------------------------+------------------+---------------+-------------+-------+---------+------------+------+-------+----------+----------------|
| 2017-05-24 10:15:07.110 -0700 | T_SALES_20170522 | SALES         | PRIVATE     | TABLE |         |            |    4 |  1024 | SYSADMIN | 1              |
+-------------------------------+------------------+---------------+-------------+-------+---------+------------+------+-------+----------+----------------+

SELECT * FROM T_SALES_20170522;

+---------+
| NUMERIC |
|---------|
|       1 |
|       2 |
|       3 |
+---------+