0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SnowflakeでCLONEした時の各データベースオブジェクトの挙動

Posted at

はじめに

Snowflakeにはゼロコピークローンと呼ばれる機能があり、追加のストレージコストをかけることなくデータベースやスキーマ、テーブルのコピーを作成することができます。
このゼロコピークローンを行った時のオブジェクトの挙動で気になるものがあったので、実際に試して記事にまとめてみました。

概要

この記事ではデータベースやスキーマをクローンした際に、下記のオブジェクト等がどのような挙動をするのかを実際に試しながら説明していきます。

  • テーブルの外部キー制約
  • VIEW
  • 権限

クローンオブジェクトの作成方法

クローンオブジェクトを作成する構文は下記です。

create <オブジェクトタイプ> <クローンオブジェクト名> clone <ソースオブジェクト名>;

例えばTEST_DBというデータベースをクローンしてTEST_DB_CLONEというデータベースを作成するためのクエリは下記になります。

create database TEST_DB_CLONE clone TEST_DB;

テーブルの外部キー制約

Snowflakeには他のデータベースシステムと同様に外部キー制約を定義することができます。
(定義することはできても、その制約は強制はされません)

クローン時の外部キー制約の挙動について、ドキュメントにはこのように書いてあります。

外部キー制約のあるテーブルがクローンされると、クローンされたテーブルは、主キーを含むソースまたはクローンされたテーブルを参照します。

  • 両方のテーブルを含むデータベースまたはスキーマがクローンされる場合、外部キーを持つクローンされたテーブルは、他のクローンされたテーブルの主キーを参照します。
  • テーブルが別々のデータベースまたはスキーマにある場合、クローンされたテーブルは、ソーステーブルの主キーを参照します。

ざっくりとした解釈としては、データベース(or スキーマ)をクローンする時、あるテーブルが外部キーとして参照しているテーブルが「同じデータベース内にある」か「別のデータベース内にある」かで挙動が異なるということみたいです。

実際に挙動を見ていきます。
まずCOMPANY_ACOMPANY_Bというデータベースを作り、それぞれにIDカラムをPKとするDEPARTMENTテーブルを作成します。

worksheets
create database COMPANY_A;
create database COMPANY_B;

create table COMPANY_A.PUBLIC.DEPARTMENT (
    ID INTEGER NOT NULL,
    NAME VARCHAR,
    CONSTRAINT pk PRIMARY KEY (ID)
);
create table COMPANY_B.PUBLIC.DEPARTMENT (
    ID INTEGER NOT NULL,
    NAME VARCHAR,
    CONSTRAINT pk PRIMARY KEY (ID)
);

その後、COMPANY_Aデータベース内に、EMPLOYEE_AテーブルとEMPLOYEE_Bテーブルを作成します。

外部キーは下記のように定義していきます。

  • EMPLOYEE_Aテーブルは自分と同じCOMPANY_AデータベースにあるDEPARTMENTテーブルを参照
  • EMPLOYEE_Bテーブルは自分とは別のCOMPANY_BデータベースにあるDEPARTMENTテーブルを参照
worksheets
-- 自分と同じデータベース内のテーブルを参照
create table COMPANY_A.PUBLIC.EMPLOYEE_A (
    DEPARTMENT_ID INTEGER NOT NULL,
    NAME VARCHAR,
    CONSTRAINT fk FOREIGN KEY (DEPARTMENT_ID) REFERENCES COMPANY_A.PUBLIC.DEPARTMENT (ID)
);

-- 自分とは別のデータベース内のテーブルを参照
create table COMPANY_A.PUBLIC.EMPLOYEE_B (
    DEPARTMENT_ID INTEGER NOT NULL,
    NAME VARCHAR,
    CONSTRAINT fk FOREIGN KEY (DEPARTMENT_ID) REFERENCES COMPANY_B.PUBLIC.DEPARTMENT (ID)
);

ここでCOMPANY_Aデータベースをクローンしました。

worksheets
create database COMPANY_A_CLONE clone COMPANY_A;

クローンされたデータベースCOMPANY_A_CLONE内のテーブルを見てみると、元々同じデータベース内のテーブルを参照していたEMPLOYEE_Aは、クローンデータベースであるCOMPANY_A_CLONEデータベース内のテーブルを参照してします。
スクリーンショット 2023-08-18 3.12.35.png
一方、元々別のデータベース内のテーブルを参照していたEMPLOYEE_Bは、クローン後も変わらずCOMPANY_Bデータベース内のテーブルを参照し続けています。
スクリーンショット 2023-08-18 3.12.45.png

図にまとめると下記のような挙動になります。

  • クローン前
    スクリーンショット 2023-07-26 1.06.58.png

  • クローン後
    スクリーンショット 2023-07-26 1.07.15.png

つまり、

  • 外部キーとして同じデータベース内のテーブルを参照している時はデータベースごとクローンされるとクローンされたデータベース内のテーブルを参照する
  • 別のデータベースを参照しているものはクローン後も別のデータベースを参照し続ける

という挙動になります。
これは多くの人のイメージ通りかなと思います。

VIEW

次にVIEWの挙動です。
データベースやスキーマをクローンした時のVIEWの挙動で注意すべきは、VIEW定義のfrom句で指定するテーブルがどの程度修飾されているか です。

下記のようなテーブルの修飾の度合いの違いにより、クローンした時の挙動が異なってきます。

  • テーブルが完全修飾されているパターン
    • select * from <db>.<schema>.<table>
  • テーブルが修飾されていないパターン
    • select * from <table>

実際に試してみます。
まずTEST_DBデータベースを作成し、その中にIDカラムを持つTEST_TABLEテーブルを作成します。

worksheets
create database TEST_DB;
create table TEST_DB.PUBLIC.TEST_TABLE (ID NUMBER);

次に参照するテーブルの修飾の度合いを変えた3パターンのVIEWを用意します。

  • 修飾なし(<table>
worksheets
create view TEST_DB.PUBLIC.VIEW_A as
select * from TEST_TABLE;
  • スキーマのみ修飾(<schema>.<table>
worksheets
create view TEST_DB.PUBLIC.VIEW_B as
select * from PUBLIC.TEST_TABLE;
  • 完全修飾(<db>.<schema>.<table>
worksheets
create view TEST_DB.PUBLIC.VIEW_C as
select * from TEST_DB.PUBLIC.TEST_TABLE;

ここでTEST_DBをクローンします。

worksheets
create database TEST_DB_CLONE clone TEST_DB;

ソースとなるデータベースのTEST_TABLEには {1, 2, 3} という値を入れ、クローンしたデータベースのTEST_TABLEには {100, 200, 300} という値を入れておきます。

worksheets
insert into TEST_DB.PUBLIC.TEST_TABLE
values (1), (2), (3);

insert into TEST_DB_CLONE.PUBLIC.TEST_TABLE
values (100), (200), (300);

ここでクローンしたデータベースでそれぞれのVIEWを呼び出してみると、
スクリーンショット 2023-07-20 2.07.06.png
VIEW_A&VIEW_Bと、VIEW_Cで結果が分かれました。

VIEW_C(完全修飾(<db>.<schema>.<table>)のパターン)のみ、ソースデータベースTEST_DB内のテーブルを参照し続け、それ以外の2つのVIEWはクローンされた方TEST_DB_CLONEのテーブルを参照するような挙動をしました。

図にまとめるとこのようになります。

  • クローン前
    スクリーンショット 2023-07-26 2.17.47.png

  • クローン後
    スクリーンショット 2023-07-26 2.18.12.png

イメージとしては、クローンしてもVIEWの定義文自体は変わらず、クローンされたデータベース内ではその定義に忠実に従うという感じかなと思います。
テーブルの修飾を意識せずにVIEWの定義をしていると、クローンした時に予想外の挙動になる可能性もありそうなので注意が必要ですね。

今回はデータベースをクローンしましたが、スキーマをクローンした時もクローン後のVIEWは定義文通りのテーブルを参照するような挙動になります。
(今回の例で言うと、VIEW_Aと、VIEW_B&VIEW_Cで結果が分かれる)
気になる方は実際に試してみてください。

権限

最後にクローンしたオブジェクトの権限について見ていこうと思います。

ドキュメントによると、クローンされたオブジェクト自体の権限は継承されず、クローンされたオブジェクトの子オブジェクトについての権限は継承されるようです。
(例えばデータベースの子オブジェクトにはスキーマやテーブルなどが相当します。)

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

実際に確認してみます。
まずTEST_DBとその中のPUBLICスキーマにUSERADMINの権限を付与します。
スクリーンショット 2023-07-20 3.06.59.png
スクリーンショット 2023-07-20 3.04.43.png

次にTEST_DBをクローンしてTEST_DB_CLONEを作成します。(ACCOUNTADMIN権限を利用)

worksheets
create or replace database TEST_DB_CLONE clone TEST_DB;

するとデータベース自体は権限が継承されず、TEST_DB_CLONEにはUSERADMINの権限は付いていません。
スクリーンショット 2023-07-20 3.04.22.png
一方、子オブジェクトであるPUBLICスキーマの権限は維持されたままクローンされています。
スクリーンショット 2023-07-20 3.04.06.png

クローンの作成といってもコマンド自体はCREATE DATABASE ~なので、クローンデータベース自体には「データベースを作ったロールのOWNERSHIP権限のみが付く」という挙動は自然かもしれないですね。

ただテーブルのクローンに関しては CREATE ~ CLONE する時に COPY GRANTS パラメーターが使えるため、それを使用することでソースオブジェクトの権限を継承した状態でクローンを作成することができます。

まとめ

この記事ではオブジェクトをクローンした時の挙動を試してみました。
特にVIEWはテーブルを修飾しているかどうかで挙動が変わるので、クローンした時に困らないように修飾方法まで意識するのが大事だなと思いました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?